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 16, 2024
1 parent 6ab8e5a commit acbaeec
Show file tree
Hide file tree
Showing 4 changed files with 321 additions and 8 deletions.
35 changes: 32 additions & 3 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, useRef, useState} from 'react';
import {DEFAULT_THEME_NAME} from '@shopify/polaris-viz-core';

import {useExternalHideEvents} from '../../hooks';
Expand All @@ -20,8 +20,22 @@ export function Legend({
theme = DEFAULT_THEME_NAME,
}: LegendProps) {
const {hiddenIndexes} = useExternalHideEvents();
const cardDimensions = useRef([{width: 0, height: 0}]);
const cutOffIndex = useRef(data.length);

const items = data.map((legend, index) => {
cardDimensions.current.reduce((totalWidth, card, index) => {
if (totalWidth + card.width + index * 10 > 514 - 50) {
cutOffIndex.current = index;
} else {
return totalWidth + card.width;
}
}, cutOffIndex.current);

console.log(cardDimensions);

console.log(cutOffIndex);

const items = data.slice(0, cutOffIndex.current).map((legend, index) => {
if (hiddenIndexes.includes(index)) {
return null;
}
Expand All @@ -34,9 +48,24 @@ export function Legend({
colorVisionType={colorVisionType}
index={index}
theme={theme}
onDimensionChange={(dimensions) => {
cardDimensions.current[index] = dimensions;
}}
/>
);
});

return <Fragment>{items}</Fragment>;
return (
<Fragment>
{items}
{cutOffIndex.current < data.length ? (
<div
style={{
whiteSpace: 'nowrap',
color: 'white',
}}
>{`+ ${data.length - cutOffIndex.current} more`}</div>
) : null}
</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, useState, useRef} from 'react';

import {
LEGEND_ITEM_LEFT_PADDING,
Expand All @@ -12,16 +12,20 @@ import {
import {PREVIEW_ICON_SIZE} from '../../../../constants';
import {SeriesIcon} from '../../../shared/SeriesIcon';
import type {LegendData} from '../../../../types';
import {useTheme} from '../../../../hooks';
import {useResizeObserver, useTheme} from '../../../../hooks';

import style from './LegendItem.scss';

import type {RefObject} from 'react';
import {ResizeObserver as Polyfill} from '@juggle/resize-observer';

export interface LegendItemProps extends LegendData {
index: number;
activeIndex?: number;
colorVisionType?: string;
renderSeriesIcon?: () => ReactNode;
theme?: string;
onDimensionChange: ({width, height}: {width: number, height: number}) => void;
}

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



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

const colorBlindAttrs =
colorVisionType == null
Expand All @@ -60,6 +78,7 @@ export function LegendItem({
gap: LEGEND_ITEM_GAP,
}}
className={style.Legend}
ref={ref}
>
{renderSeriesIcon == null ? (
<span
Expand All @@ -80,3 +99,68 @@ export function LegendItem({
</button>
);
}




const ResizeObserver =
// eslint-disable-next-line ssr-friendly/no-dom-globals-in-module-scope
typeof window !== 'undefined' && (window.ResizeObserver || Polyfill);

export interface Dimensions {
top: number;
left: number;
width: number;
height: number;
offsetTop: number;
offsetLeft: number;
}

const getElementSize = (element: RefObject<HTMLElement | null> | null) => {
if (
element == null ||
element.current == null ||
!(element.current instanceof Element)
) {
return null;
}

const {left, width, height, top} = element.current.getBoundingClientRect();
const {offsetTop, offsetLeft} = element.current;

return {
top,
left,
width,
height,
offsetTop,
offsetLeft,
};
};

export function useElementSize(
element: RefObject<HTMLElement | null> | null,
): Dimensions | null {
const [componentSize, setComponentSize] = useState(getElementSize(element));

// Ensure we get the element size on mount
useEffect(() => {
setComponentSize(getElementSize(element));
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

useEffect(() => {
if (!element?.current || !ResizeObserver) {
return;
}
const handleResize = () => setComponentSize(getElementSize(element));

const observer = new ResizeObserver(handleResize);
observer.observe(element.current);
return () => {
observer.disconnect();
};
}, [element]);

return componentSize;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.Container {
display: flex;
gap: 10px;
flex-wrap: wrap;
flex-wrap: nowrap;
}
Loading

0 comments on commit acbaeec

Please sign in to comment.