Skip to content

Commit

Permalink
wip: add overflow to legend
Browse files Browse the repository at this point in the history
  • Loading branch information
susiekims committed Jan 17, 2024
1 parent 6ab8e5a commit 3ac9fec
Show file tree
Hide file tree
Showing 15 changed files with 791 additions and 14 deletions.
1 change: 1 addition & 0 deletions packages/polaris-viz/src/components/ComboChart/Chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@ export function Chart({
data={legend}
onDimensionChange={setLegendDimensions}
renderLegendContent={renderLegendContent}
width={width}
/>
)}
</ChartElements.Div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ export const SampleLegendChart = ({theme} = {theme: 'Default'}) => {
export const SampleLegendContainer = ({theme} = {theme: 'Default'}) => {
const selectedTheme = useTheme(theme);
const colors = getSeriesColors(6, selectedTheme);
const {legend} = useLegend({
const {legend, width} = useLegend({
data: [
{
shape: 'Line',
Expand Down Expand Up @@ -253,6 +253,7 @@ export const SampleLegendContainer = ({theme} = {theme: 'Default'}) => {
colorVisionType=""
data={legend}
onDimensionChange={() => {}}
width={width}
/>
</div>
</SimpleContainer>
Expand Down
1 change: 1 addition & 0 deletions packages/polaris-viz/src/components/DonutChart/Chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ export function Chart({
direction={legendDirection}
position={legendPosition}
maxWidth={maxLegendWidth}
width={width}
renderLegendContent={
shouldRenderLegendContentWithValues
? renderLegendContentWithValues
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ export function Chart({
data={legend}
onDimensionChange={setLegendDimensions}
renderLegendContent={renderLegendContent}
width={width}
/>
)}
</ChartElements.Div>
Expand Down
15 changes: 13 additions & 2 deletions packages/polaris-viz/src/components/Legend/Legend.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Fragment} from 'react';
import {Fragment, type RefObject} from 'react';
import {DEFAULT_THEME_NAME} from '@shopify/polaris-viz-core';

import {useExternalHideEvents} from '../../hooks';
Expand All @@ -11,13 +11,15 @@ export interface LegendProps {
activeIndex?: number;
colorVisionType?: string;
theme?: string;
cardDimensions: RefObject<{width: number; height: number}[]>;
}

export function Legend({
activeIndex = -1,
colorVisionType,
data,
theme = DEFAULT_THEME_NAME,
cardDimensions,
}: LegendProps) {
const {hiddenIndexes} = useExternalHideEvents();

Expand All @@ -34,9 +36,18 @@ export function Legend({
colorVisionType={colorVisionType}
index={index}
theme={theme}
onDimensionChange={(dimensions) => {
if (cardDimensions.current != null) {
cardDimensions.current[index] = dimensions;
}
}}
/>
);
});

return <Fragment>{items}</Fragment>;
return (
<Fragment>
{items}
</Fragment>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {
getColorVisionEventAttrs,
getColorVisionStylesForActiveIndex,
} from '@shopify/polaris-viz-core';
import type {ReactNode} from 'react';
import {useEffect, type ReactNode, useRef} from 'react';

import {
LEGEND_ITEM_LEFT_PADDING,
Expand All @@ -22,6 +22,7 @@ export interface LegendItemProps extends LegendData {
colorVisionType?: string;
renderSeriesIcon?: () => ReactNode;
theme?: string;
onDimensionChange?: ({width, height}: {width: number, height: number}) => void;
}

export function LegendItem({
Expand All @@ -35,8 +36,17 @@ export function LegendItem({
shape,
theme,
value,
onDimensionChange,
}: LegendItemProps) {
const selectedTheme = useTheme(theme);
const ref = useRef<HTMLButtonElement | null>(null)

useEffect(() => {
if (onDimensionChange && ref.current != null) {
const {width, height} = ref.current.getBoundingClientRect();
onDimensionChange({width, height});
}
}, [onDimensionChange, ref]);

const colorBlindAttrs =
colorVisionType == null
Expand All @@ -60,6 +70,7 @@ export function LegendItem({
gap: LEGEND_ITEM_GAP,
}}
className={style.Legend}
ref={ref}
>
{renderSeriesIcon == null ? (
<span
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
.Container {
display: flex;
gap: 10px;
flex-wrap: wrap;
}

.MoreText {
color: white;
display: flex;
white-space: nowrap;
align-items: center;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type {CSSProperties, Dispatch, SetStateAction} from 'react';
import {useEffect, useRef, useState} from 'react';
import {useEffect, useMemo, useRef, useState} from 'react';
import isEqual from 'fast-deep-equal';
import {
getColorVisionEventAttrs,
Expand All @@ -23,6 +23,10 @@ import {classNames} from '../../utilities';

import style from './LegendContainer.scss';

const MORE_TEXT_WIDTH = 50;
const MAX_VERTICAL_LEGEND_ITEMS = 5;
const LEGEND_GAP = 10;

export interface LegendContainerProps {
colorVisionType: string;
data: LegendData[];
Expand All @@ -32,6 +36,8 @@ export interface LegendContainerProps {
position?: LegendPosition;
maxWidth?: number;
renderLegendContent?: RenderLegendContent;
onItemDimensionChange?: any;
width: number;
}

export function LegendContainer({
Expand All @@ -43,6 +49,7 @@ export function LegendContainer({
position = 'bottom-right',
maxWidth,
renderLegendContent,
width,
}: LegendContainerProps) {
const selectedTheme = useTheme();
const {setRef, entry} = useResizeObserver();
Expand All @@ -57,13 +64,46 @@ export function LegendContainer({
const {horizontalMargin} = selectedTheme.grid;
const leftMargin = isPositionLeft ? 0 : horizontalMargin;

const cardDimensions = useRef([{width: 0, height: 0}]);

const truncatedLegend = useMemo(() => {
if (direction === 'vertical') {
return data.slice(0, MAX_VERTICAL_LEGEND_ITEMS);
} else {
let cutOffIndex = data.length;
const containerWidth =
width - leftMargin - horizontalMargin - MORE_TEXT_WIDTH;

cardDimensions.current.reduce((totalWidth, card, index) => {
if (totalWidth + card.width + index * LEGEND_GAP > containerWidth) {
cutOffIndex = index;
} else {
return totalWidth + card.width;
}
}, cutOffIndex);

return data.slice(0, cutOffIndex);
}
}, [
cardDimensions.current,
direction,
data,
width,
leftMargin,
horizontalMargin,
]);

const shouldTruncateLegend =
truncatedLegend.length < data.length && data.length > 2;

const styleMap: {[key: string]: CSSProperties} = {
horizontal: {
justifyContent: 'flex-end',
margin: isPositionTop
? `0 ${horizontalMargin}px ${LEGENDS_BOTTOM_MARGIN}px ${leftMargin}px`
: `${LEGENDS_TOP_MARGIN}px ${horizontalMargin}px 0 ${leftMargin}px`,
flexDirection: 'row',
flexWrap: shouldTruncateLegend ? 'nowrap' : 'wrap',
},
vertical: {
alignItems: 'flex-start',
Expand Down Expand Up @@ -125,12 +165,20 @@ export function LegendContainer({
style={{...styleMap[direction], ...shouldCenterTiles(position)}}
>
{renderLegendContent?.(colorVisionInteractionMethods) ?? (
<Legend
activeIndex={activeIndex}
colorVisionType={colorVisionType}
data={data}
theme={theme}
/>
<>
<Legend
activeIndex={activeIndex}
colorVisionType={colorVisionType}
data={shouldTruncateLegend ? truncatedLegend : data}
theme={theme}
cardDimensions={cardDimensions}
/>
{shouldTruncateLegend && (
<div className={style.MoreText}>
{`+${data.length - truncatedLegend.length} more`}
</div>
)}
</>
)}
</div>
);
Expand Down
1 change: 1 addition & 0 deletions packages/polaris-viz/src/components/LineChart/Chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,7 @@ export function Chart({
data={legend}
onDimensionChange={setLegendDimensions}
renderLegendContent={renderLegendContent}
width={width}
/>
)}
</Fragment>
Expand Down
Loading

0 comments on commit 3ac9fec

Please sign in to comment.