diff --git a/lerna.json b/lerna.json index 5cd2efdb81..3721d04a86 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "10.2.1", + "version": "1.0.0-line-chart-predictive-beta.3", "npmClient": "yarn", "useWorkspaces": true, "ignoreChanges": [ diff --git a/package.json b/package.json index 64fe813d38..f346f7ca41 100644 --- a/package.json +++ b/package.json @@ -160,5 +160,6 @@ }, "dependencies": { "concurrently": "^7.0.0" - } + }, + "version": "v1.0.0-line-chart-predictive-beta.2" } diff --git a/packages/polaris-viz-core/src/components/LineSeries/LineSeries.tsx b/packages/polaris-viz-core/src/components/LineSeries/LineSeries.tsx index 850d89ec29..746ead68c3 100644 --- a/packages/polaris-viz-core/src/components/LineSeries/LineSeries.tsx +++ b/packages/polaris-viz-core/src/components/LineSeries/LineSeries.tsx @@ -42,13 +42,15 @@ export function LineSeries({ activeLineIndex = -1, data, hiddenIndexes = [], - index = 0, + index: lineSeriesIndex = 0, svgDimensions, theme, type = 'default', xScale, yScale, }: LineSeriesProps) { + const index = data?.metadata?.relatedIndex ?? lineSeriesIndex; + const { // eslint-disable-next-line id-length components: {Defs, Mask, G, Rect, Path}, diff --git a/packages/polaris-viz/package.json b/packages/polaris-viz/package.json index fb699c488b..b5f39bb1f4 100644 --- a/packages/polaris-viz/package.json +++ b/packages/polaris-viz/package.json @@ -1,7 +1,7 @@ { "name": "@shopify/polaris-viz", "description": "Shopify’s viz component library", - "version": "10.2.1", + "version": "1.0.0-line-chart-predictive-beta.3", "private": false, "license": "SEE LICENSE IN LICENSE.md", "author": "Shopify ", diff --git a/packages/polaris-viz/src/components/LineChart/Chart.tsx b/packages/polaris-viz/src/components/LineChart/Chart.tsx index e833f5a741..2b2e6dd2ff 100644 --- a/packages/polaris-viz/src/components/LineChart/Chart.tsx +++ b/packages/polaris-viz/src/components/LineChart/Chart.tsx @@ -152,8 +152,7 @@ export function Chart({ verticalOverflow: selectedTheme.grid.verticalOverflow, }); - const {reversedSeries, longestSeriesLength, longestSeriesIndex} = - useFormatData(data); + const {longestSeriesLength, longestSeriesIndex} = useFormatData(data); const { drawableWidth, @@ -208,11 +207,7 @@ export function Chart({ if (eventType === 'mouse') { const point = eventPointNative(event!); - if ( - point == null || - xScale == null || - reversedSeries[longestSeriesIndex] == null - ) { + if (point == null || xScale == null || data[longestSeriesIndex] == null) { return TOOLTIP_POSITION_DEFAULT_RETURN; } @@ -223,7 +218,7 @@ export function Chart({ const activeIndex = clamp({ amount: closestIndex, min: 0, - max: reversedSeries[longestSeriesIndex].data.length - 1, + max: data[longestSeriesIndex].data.length - 1, }); return { @@ -340,13 +335,13 @@ export function Chart({ theme, })} - {reversedSeries.map((singleSeries, index) => { + {data.map((singleSeries, index) => { return ( - {data.map((singleSeries, index) => { - const unreversedIndex = data.length - 1 - index; + {data.map((singleSeries, seriesIndex) => { + const index = singleSeries.metadata?.relatedIndex ?? seriesIndex; - if (hiddenIndexes.includes(unreversedIndex)) { + if (hiddenIndexes.includes(index)) { return null; } @@ -85,11 +85,13 @@ export function Points({ : singleData[activeIndex ?? -1]?.value != null; const isLineActive = - activeLineIndex !== -1 && activeLineIndex !== unreversedIndex; + activeLineIndex !== -1 && activeLineIndex !== index; - const hidePoint = + const isPointVisuallyHidden = !hasValidData || animatedCoordinates == null || isLineActive; + const isPointActive = hasValidData && activeIndex != null; + const pointColor = isGradientType(color) ? `url(#${pointGradientId})` : changeColorOpacity(color); @@ -112,11 +114,11 @@ export function Points({ color={pointColor} cx={getXPosition({isCrosshair: false})} cy={animatedYPosition} - active={hasValidData && activeIndex != null} + active={isPointActive} index={index} tabIndex={-1} isAnimated={shouldAnimate} - visuallyHidden={hidePoint} + visuallyHidden={isPointVisuallyHidden} ariaHidden /> ) : null} @@ -131,7 +133,7 @@ export function Points({ key={`${name}-${index}-${dataIndex}`} style={getColorVisionStylesForActiveIndex({ activeIndex: activeLineIndex, - index: data.length - 1 - index, + index, fadedOpacity: 0, })} > diff --git a/packages/polaris-viz/src/components/LineChart/components/PointsAndCrosshair/PointsAndCrosshair.tsx b/packages/polaris-viz/src/components/LineChart/components/PointsAndCrosshair/PointsAndCrosshair.tsx index 7d31898a66..0dfb0ba437 100644 --- a/packages/polaris-viz/src/components/LineChart/components/PointsAndCrosshair/PointsAndCrosshair.tsx +++ b/packages/polaris-viz/src/components/LineChart/components/PointsAndCrosshair/PointsAndCrosshair.tsx @@ -19,24 +19,24 @@ import {Points} from '../Points'; interface PointsAndCrosshairProps { activeIndex: number | null; + data: LineChartDataSeriesWithDefaults[]; drawableHeight: number; emptyState: boolean; + hiddenIndexes?: number[]; longestSeriesIndex: number; - reversedSeries: LineChartDataSeriesWithDefaults[]; theme: string; tooltipId: string; xScale: ScaleLinear; yScale: ScaleLinear; - hiddenIndexes?: number[]; } export function PointsAndCrosshair({ activeIndex, + data, drawableHeight, emptyState, hiddenIndexes = [], longestSeriesIndex, - reversedSeries, theme, tooltipId, xScale, @@ -59,7 +59,7 @@ export function PointsAndCrosshair({ }, [selectedTheme.line.hasSpline, xScale, yScale]); const {animatedCoordinates} = useLinearChartAnimations({ - data: reversedSeries, + data, lineGenerator, activeIndex, }); @@ -97,7 +97,7 @@ export function PointsAndCrosshair({ data.slice().reverse(), [data]); - const longestSeriesIndex = useMemo( () => - reversedSeries.reduce((maxIndex, currentSeries, currentIndex) => { - return reversedSeries[maxIndex].data.length < currentSeries.data.length + data.reduce((maxIndex, currentSeries, currentIndex) => { + return data[maxIndex].data.length < currentSeries.data.length ? currentIndex : maxIndex; }, 0), - [reversedSeries], + [data], ); - const longestSeriesLength = reversedSeries[longestSeriesIndex] - ? reversedSeries[longestSeriesIndex].data.length - 1 + const longestSeriesLength = data[longestSeriesIndex] + ? data[longestSeriesIndex].data.length - 1 : 0; - return {reversedSeries, longestSeriesLength, longestSeriesIndex}; + return {longestSeriesLength, longestSeriesIndex}; } diff --git a/packages/polaris-viz/src/components/LineChartPredictive/LineChartPredictive.tsx b/packages/polaris-viz/src/components/LineChartPredictive/LineChartPredictive.tsx index 57fc7a04c5..371ca58dee 100644 --- a/packages/polaris-viz/src/components/LineChartPredictive/LineChartPredictive.tsx +++ b/packages/polaris-viz/src/components/LineChartPredictive/LineChartPredictive.tsx @@ -1,14 +1,18 @@ +import type {DataSeries} from '@shopify/polaris-viz-core'; import { DEFAULT_CHART_PROPS, DEFAULT_THEME_NAME, useTheme, useThemeSeriesColors, } from '@shopify/polaris-viz-core'; +import {useMemo} from 'react'; +import type {RenderTooltipContentData} from 'types'; import {LineChart} from '../LineChart'; import type {LineChartPredictiveProps} from './types'; -import {CustomLegend, PredictiveLineSeries} from './components'; +import {CustomLegend, PredictiveLinePoints} from './components'; +import {renderLinearPredictiveTooltipContent} from './utilities/renderLinearPredictiveTooltipContent'; export function LineChartPredictive(props: LineChartPredictiveProps) { const { @@ -22,7 +26,7 @@ export function LineChartPredictive(props: LineChartPredictiveProps) { skipLinkText, state, theme, - tooltipOptions, + tooltipOptions: initialTooltipOptions, xAxisOptions, yAxisOptions, } = { @@ -41,19 +45,44 @@ export function LineChartPredictive(props: LineChartPredictiveProps) { } } + const selectedTheme = useTheme(theme); + const seriesColors = useThemeSeriesColors(nonPredictiveData, selectedTheme); + const predictiveSeriesNames = predictiveData .map(({metadata}) => { return data[metadata?.relatedIndex ?? -1].name; }) .filter((value) => value != null) as string[]; - const selectedTheme = useTheme(theme); - const seriesColors = useThemeSeriesColors(nonPredictiveData, selectedTheme); + const dataWithColors: DataSeries[] = []; + let index = -1; + + for (const series of data) { + if (series.metadata?.relatedIndex == null) { + index += 1; + } + + dataWithColors.push({ + ...series, + color: seriesColors[index], + }); + } + + const tooltipOptions = useMemo(() => { + function renderTooltipContent(tooltipData: RenderTooltipContentData) { + return renderLinearPredictiveTooltipContent(tooltipData); + } + + return { + ...initialTooltipOptions, + renderTooltipContent, + }; + }, [initialTooltipOptions]); return ( { return ( - ); diff --git a/packages/polaris-viz/src/components/LineChartPredictive/components/CustomLegend/CustomLegend.scss b/packages/polaris-viz/src/components/LineChartPredictive/components/CustomLegend/CustomLegend.scss index d1e05d3d4d..7900c36491 100644 --- a/packages/polaris-viz/src/components/LineChartPredictive/components/CustomLegend/CustomLegend.scss +++ b/packages/polaris-viz/src/components/LineChartPredictive/components/CustomLegend/CustomLegend.scss @@ -4,11 +4,3 @@ flex-wrap: wrap; list-style: none; } - -.IconContainer { - display: flex; - align-items: center; - justify-items: center; - height: 12px; - width: 20px; -} diff --git a/packages/polaris-viz/src/components/LineChartPredictive/components/CustomLegend/CustomLegend.tsx b/packages/polaris-viz/src/components/LineChartPredictive/components/CustomLegend/CustomLegend.tsx index f577a7b092..b962237da6 100644 --- a/packages/polaris-viz/src/components/LineChartPredictive/components/CustomLegend/CustomLegend.tsx +++ b/packages/polaris-viz/src/components/LineChartPredictive/components/CustomLegend/CustomLegend.tsx @@ -1,25 +1,13 @@ -import { - LinearGradientWithStops, - changeGradientOpacity, - isGradientType, - uniqueId, -} from '@shopify/polaris-viz-core'; -import type {Color} from '@shopify/polaris-viz-core'; -import {useMemo} from 'react'; - import type {LineChartPredictiveDataSeries} from '../../../../components/LineChartPredictive/types'; import type {ColorVisionInteractionMethods} from '../../../../types'; -import {getLineChartDataWithDefaults} from '../../../../utilities/getLineChartDataWithDefaults'; import {LegendItem} from '../../../../components/Legend'; +import {SeriesIcon} from '../SeriesIcon'; import styles from './CustomLegend.scss'; interface Props extends ColorVisionInteractionMethods { data: LineChartPredictiveDataSeries[]; predictiveSeriesNames: string[]; - getColorVisionEventAttrs: any; - getColorVisionStyles: any; - seriesColors: Color[]; theme: string; } @@ -28,20 +16,17 @@ export function CustomLegend({ predictiveSeriesNames, getColorVisionEventAttrs, getColorVisionStyles, - seriesColors, theme, }: Props) { - const id = useMemo(() => uniqueId('CustomLegen'), []); - - const dataWithDefaults = getLineChartDataWithDefaults(data, seriesColors); - return (
    - {dataWithDefaults.map(({color, name, isComparison}, index) => { - const gradientId = `${id}-${index}`; + {data.map(({color, name, isComparison, metadata}, index) => { + if (metadata?.isPredictive) { + return null; + } function renderSeriesIcon() { - return ; + return ; } return ( @@ -71,35 +56,3 @@ export function CustomLegend({
); } - -function SeriesIcon({color, gradientId}: {color: Color; gradientId: string}) { - return ( -
- - - {isGradientType(color) ? ( - - - - ) : null} - -
- ); -} diff --git a/packages/polaris-viz/src/components/LineChartPredictive/components/PredictiveLineSeries/PredictiveLineSeries.tsx b/packages/polaris-viz/src/components/LineChartPredictive/components/PredictiveLinePoints/PredictiveLinePoints.tsx similarity index 64% rename from packages/polaris-viz/src/components/LineChartPredictive/components/PredictiveLineSeries/PredictiveLineSeries.tsx rename to packages/polaris-viz/src/components/LineChartPredictive/components/PredictiveLinePoints/PredictiveLinePoints.tsx index b4eec68f88..2ae6c58b5e 100644 --- a/packages/polaris-viz/src/components/LineChartPredictive/components/PredictiveLineSeries/PredictiveLineSeries.tsx +++ b/packages/polaris-viz/src/components/LineChartPredictive/components/PredictiveLinePoints/PredictiveLinePoints.tsx @@ -1,7 +1,5 @@ -import type {Color} from '@shopify/polaris-viz-core'; import { COLOR_VISION_SINGLE_ITEM, - LineSeries, LinearGradientWithStops, changeColorOpacity, changeGradientOpacity, @@ -11,46 +9,42 @@ import { import {Fragment, useMemo, useState} from 'react'; import type {LineChartSlotProps} from 'types'; -import {Point} from '../../../../components/Point'; +import {Point} from '../../../Point'; import {useWatchColorVisionEvents} from '../../../../hooks'; -import {getLineChartDataWithDefaults} from '../../../../utilities/getLineChartDataWithDefaults'; import type {LineChartPredictiveProps} from '../../types'; -interface PredictiveLinesProps extends LineChartSlotProps { +interface PredictiveLinePointsProps extends LineChartSlotProps { data: LineChartPredictiveProps['data']; - seriesColors: Color[]; - theme: string; } -export function PredictiveLineSeries({ +export function PredictiveLinePoints({ data, - drawableHeight, - drawableWidth, - seriesColors, - theme, xScale, yScale, -}: PredictiveLinesProps) { +}: PredictiveLinePointsProps) { const [activeLineIndex, setActiveLineIndex] = useState(-1); - const id = useMemo(() => uniqueId('PredictiveLines'), []); + const id = useMemo(() => uniqueId('PredictiveLinePoints'), []); useWatchColorVisionEvents({ type: COLOR_VISION_SINGLE_ITEM, onIndexChange: ({detail}) => setActiveLineIndex(detail.index), }); - const dataWithDefaults = getLineChartDataWithDefaults(data, seriesColors); - return ( - {dataWithDefaults.map((series, index) => { + {data.map((series, seriesIndex) => { + if (series.metadata?.isPredictive == null) { + return false; + } + + const index = series.metadata?.relatedIndex ?? seriesIndex; const pointGradientId = `${id}-point-${index}`; const predictiveStartIndex = series.data.findIndex( ({key}) => key === series.metadata?.startKey, ); - const color = series.color; + const color = series.color!; const pointColor = isGradientType(color) ? `url(#${pointGradientId})` @@ -58,18 +52,6 @@ export function PredictiveLineSeries({ return ( - {isGradientType(color) ? ( uniqueId('SeriesIcon'), []); + + return ( +
+ + + {isGradientType(color) ? ( + + + + ) : null} + +
+ ); +} diff --git a/packages/polaris-viz/src/components/LineChartPredictive/components/SeriesIcon/index.ts b/packages/polaris-viz/src/components/LineChartPredictive/components/SeriesIcon/index.ts new file mode 100644 index 0000000000..67ffefcd7e --- /dev/null +++ b/packages/polaris-viz/src/components/LineChartPredictive/components/SeriesIcon/index.ts @@ -0,0 +1 @@ +export {SeriesIcon} from './SeriesIcon'; diff --git a/packages/polaris-viz/src/components/LineChartPredictive/components/index.ts b/packages/polaris-viz/src/components/LineChartPredictive/components/index.ts index 62b896d03d..fe18bba2b1 100644 --- a/packages/polaris-viz/src/components/LineChartPredictive/components/index.ts +++ b/packages/polaris-viz/src/components/LineChartPredictive/components/index.ts @@ -1,2 +1,3 @@ -export {PredictiveLineSeries} from './PredictiveLineSeries'; +export {PredictiveLinePoints} from './PredictiveLinePoints'; export {CustomLegend} from './CustomLegend'; +export {SeriesIcon} from './SeriesIcon'; diff --git a/packages/polaris-viz/src/components/LineChartPredictive/stories/playground/DynamicData.stories.tsx b/packages/polaris-viz/src/components/LineChartPredictive/stories/playground/DynamicData.stories.tsx new file mode 100644 index 0000000000..f9258f2445 --- /dev/null +++ b/packages/polaris-viz/src/components/LineChartPredictive/stories/playground/DynamicData.stories.tsx @@ -0,0 +1,440 @@ +import {LineChartPredictive} from '../../LineChartPredictive'; +import type {DataSeries} from '@shopify/polaris-viz-core'; + +export {META as default} from '../meta'; + +// const DATA: DataSeries[] = [ +// { +// name: 'January 2023-December 2023', +// data: [ +// { +// key: 0, +// value: 70, +// }, +// { +// key: 1, +// value: 80, +// }, +// { +// key: 2, +// value: 87, +// }, +// { +// value: null, +// key: 3, +// }, +// { +// value: null, +// key: 4, +// }, +// { +// value: null, +// key: 5, +// }, +// { +// value: null, +// key: 6, +// }, +// { +// value: null, +// key: 7, +// }, +// { +// value: null, +// key: 8, +// }, +// { +// value: null, +// key: 9, +// }, +// { +// value: null, +// key: 10, +// }, +// { +// value: null, +// key: 11, +// }, +// ], +// styleOverride: { +// line: { +// hasArea: false, +// }, +// }, +// }, +// { +// name: 'January 2023-December 2023', +// data: [ +// { +// value: null, +// key: 0, +// }, +// { +// value: null, +// key: 1, +// }, +// { +// key: 2, +// value: 87, +// }, +// { +// key: 3, +// value: 93, +// }, +// { +// key: 4, +// value: 96, +// }, +// { +// key: 5, +// value: 102, +// }, +// { +// key: 6, +// value: 104, +// }, +// { +// key: 7, +// value: 105, +// }, +// { +// key: 8, +// value: 106, +// }, +// { +// key: 9, +// value: 107, +// }, +// { +// key: 10, +// value: 108, +// }, +// { +// key: 11, +// value: 109, +// }, +// ], +// styleOverride: { +// line: { +// strokeDasharray: '1 10 1', +// hasArea: false, +// }, +// }, +// metadata: { +// relatedIndex: 0, +// isPredictive: true, +// startKey: 2, +// }, +// }, +// { +// data: [ +// { +// key: 0, +// value: 70, +// }, +// { +// key: 1, +// value: 57, +// }, +// { +// key: 2, +// value: 62, +// }, +// { +// key: 3, +// value: 67, +// }, +// { +// key: 4, +// value: 69, +// }, +// { +// key: 5, +// value: 72, +// }, +// { +// key: 6, +// value: 73, +// }, +// { +// key: 7, +// value: 75, +// }, +// { +// key: 8, +// value: 77, +// }, +// { +// key: 9, +// value: 78, +// }, +// { +// key: 10, +// value: 79, +// }, +// { +// key: 11, +// value: 81, +// }, +// ], +// isComparison: true, +// name: 'January 2022-December 2022', +// }, +// ]; + +const DATA: DataSeries[] = [ + { + name: 'January 2023-December 2023', + data: [ + { + key: 0, + value: 70, + }, + { + key: 1, + value: 80, + }, + { + key: 2, + value: 87, + }, + { + value: null, + key: 3, + }, + { + value: null, + key: 4, + }, + { + value: null, + key: 5, + }, + ], + styleOverride: { + line: { + hasArea: false, + }, + }, + }, + { + name: 'January 2023-December 2023', + data: [ + { + value: null, + key: 0, + }, + { + value: null, + key: 1, + }, + { + key: 2, + value: 87, + }, + { + key: 3, + value: 93, + }, + { + key: 4, + value: 96, + }, + { + key: 5, + value: 102, + }, + ], + styleOverride: { + line: { + strokeDasharray: '1 10 1', + hasArea: false, + }, + }, + metadata: { + relatedIndex: 0, + isPredictive: true, + startKey: 2, + }, + }, + // + { + name: 'Aug 2023-December 2023', + data: [ + { + key: 0, + value: 170, + }, + { + key: 1, + value: 180, + }, + { + key: 2, + value: 187, + }, + { + value: null, + key: 3, + }, + { + value: null, + key: 4, + }, + { + value: null, + key: 5, + }, + ], + styleOverride: { + line: { + hasArea: false, + }, + }, + }, + { + name: 'Aug 2023-December 2023', + data: [ + { + value: null, + key: 0, + }, + { + value: null, + key: 1, + }, + { + key: 2, + value: 187, + }, + { + key: 3, + value: 193, + }, + { + key: 4, + value: 196, + }, + { + key: 5, + value: 1102, + }, + ], + styleOverride: { + line: { + strokeDasharray: '1 10 1', + hasArea: false, + }, + }, + metadata: { + relatedIndex: 2, + isPredictive: true, + startKey: 2, + }, + }, + // + { + data: [ + { + key: 0, + value: 70, + }, + { + key: 1, + value: 57, + }, + { + key: 2, + value: 62, + }, + { + key: 3, + value: 67, + }, + { + key: 4, + value: 69, + }, + { + key: 5, + value: 72, + }, + ], + isComparison: true, + name: 'January 2022-December 2022', + }, +]; + +export const DynamicData = () => { + // const [data, setData] = useState([ + // { + // name: 'BCFM 2019', + // data: [ + // { + // key: 'Womens Leggings', + // value: 3, + // }, + // { + // key: 'Mens Bottoms', + // value: 7, + // }, + // { + // key: 'Mens Shorts', + // value: 4, + // }, + // ], + // }, + // { + // name: 'BCFM 2020', + // data: [ + // { + // key: 'Womens Leggings', + // value: 1, + // }, + // { + // key: 'Mens Bottoms', + // value: 2, + // }, + // { + // key: 'Mens Shorts', + // value: 5, + // }, + // ], + // }, + // ]); + + // const onClick = () => { + // const newData = data.map((series) => { + // return { + // ...series, + // data: series.data.map(({key}) => { + // const newValue = Math.floor(Math.random() * 200); + // return { + // key, + // value: newValue, + // }; + // }), + // }; + // }); + + // setData(newData); + // }; + + return ( + <> +
+ +
+ {/* */} + + ); +}; diff --git a/packages/polaris-viz/src/components/LineChartPredictive/utilities/Styles.scss b/packages/polaris-viz/src/components/LineChartPredictive/utilities/Styles.scss new file mode 100644 index 0000000000..a72dfb67e5 --- /dev/null +++ b/packages/polaris-viz/src/components/LineChartPredictive/utilities/Styles.scss @@ -0,0 +1,6 @@ +.Icon { + display: flex; + align-items: center; + justify-content: center; + margin-right: 4px; +} diff --git a/packages/polaris-viz/src/components/LineChartPredictive/utilities/renderLinearPredictiveTooltipContent.tsx b/packages/polaris-viz/src/components/LineChartPredictive/utilities/renderLinearPredictiveTooltipContent.tsx new file mode 100644 index 0000000000..4432b9b75c --- /dev/null +++ b/packages/polaris-viz/src/components/LineChartPredictive/utilities/renderLinearPredictiveTooltipContent.tsx @@ -0,0 +1,90 @@ +import type {ReactNode} from 'react'; +import {Fragment} from 'react'; + +import {PREVIEW_ICON_SIZE} from '../../../constants'; +import { + TooltipContentContainer, + TooltipTitle, + TooltipRow, + LinePreview, +} from '../../'; +import type {RenderTooltipContentData} from '../../../types'; +import {SeriesIcon} from '../components'; + +import styles from './Styles.scss'; + +export function renderLinearPredictiveTooltipContent( + tooltipData: RenderTooltipContentData, +): ReactNode { + const {theme} = tooltipData; + + const formatters = { + keyFormatter: (key) => `${key}`, + valueFormatter: (value) => `${value}`, + titleFormatter: (title) => `${title}`, + ...tooltipData.formatters, + }; + + function renderSeriesIcon(color, isComparison): ReactNode { + return ( +
+ {isComparison ? ( + + ) : ( + + )} +
+ ); + } + + function renderContent({ + activeColorVisionIndex, + }: { + activeColorVisionIndex: number; + }) { + const item = tooltipData.data[0]; + + return item.data.map(({color, key, value, isComparison}, seriesIndex) => { + const metadata = tooltipData.dataSeries[seriesIndex].metadata; + const activeKey = + tooltipData.dataSeries[seriesIndex].data[tooltipData.activeIndex].key; + const index = metadata?.relatedIndex ?? seriesIndex; + + const isNull = value == null; + const isPredictiveStartKey = metadata?.startKey === activeKey; + const isHidden = isNull || isPredictiveStartKey; + + return ( + renderSeriesIcon(color, isComparison)} + shape="Line" + value={formatters.valueFormatter(value ?? 0)} + /> + ); + }); + } + + return ( + + {({activeColorVisionIndex}) => ( + + {tooltipData.title != null && ( + + {formatters.titleFormatter(tooltipData.title)} + + )} + {renderContent({activeColorVisionIndex})} + + )} + + ); +} diff --git a/packages/polaris-viz/src/components/StackedAreaChart/components/StackedAreas/StackedAreas.tsx b/packages/polaris-viz/src/components/StackedAreaChart/components/StackedAreas/StackedAreas.tsx index a90b52916e..7b87bfddfc 100644 --- a/packages/polaris-viz/src/components/StackedAreaChart/components/StackedAreas/StackedAreas.tsx +++ b/packages/polaris-viz/src/components/StackedAreaChart/components/StackedAreas/StackedAreas.tsx @@ -95,7 +95,7 @@ export function StackedAreas({ return ( {color != null && ( -
+
{renderSeriesIcon?.() ?? (