@automattic/charts 2.0.1 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/TOKENS.md +109 -50
  3. package/dist/index.cjs +529 -233
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.css +118 -55
  6. package/dist/index.d.cts +90 -48
  7. package/dist/index.d.ts +90 -48
  8. package/dist/index.js +527 -235
  9. package/dist/index.js.map +1 -1
  10. package/package.json +1 -1
  11. package/src/charts/area-chart/area-chart.module.scss +8 -3
  12. package/src/charts/area-chart/area-chart.tsx +25 -25
  13. package/src/charts/area-chart/private/overlays.tsx +3 -3
  14. package/src/charts/area-chart/test/area-chart.test.tsx +301 -11
  15. package/src/charts/area-chart/types.ts +4 -3
  16. package/src/charts/bar-chart/bar-chart.module.scss +14 -6
  17. package/src/charts/bar-chart/bar-chart.tsx +21 -15
  18. package/src/charts/bar-chart/test/bar-chart.test.tsx +255 -2
  19. package/src/charts/conversion-funnel-chart/conversion-funnel-chart.module.scss +23 -18
  20. package/src/charts/conversion-funnel-chart/conversion-funnel-chart.tsx +107 -86
  21. package/src/charts/conversion-funnel-chart/test/chart-scope.test.tsx +36 -0
  22. package/src/charts/geo-chart/geo-chart.module.scss +8 -0
  23. package/src/charts/geo-chart/geo-chart.tsx +12 -4
  24. package/src/charts/heatmap-chart/heatmap-chart.module.scss +22 -9
  25. package/src/charts/heatmap-chart/heatmap-chart.tsx +43 -13
  26. package/src/charts/heatmap-chart/private/build-calendar-data.ts +65 -5
  27. package/src/charts/heatmap-chart/test/build-calendar-data.test.ts +125 -0
  28. package/src/charts/heatmap-chart/types.ts +8 -0
  29. package/src/charts/leaderboard-chart/leaderboard-chart.module.scss +13 -7
  30. package/src/charts/leaderboard-chart/leaderboard-chart.tsx +17 -22
  31. package/src/charts/leaderboard-chart/test/leaderboard-chart.test.tsx +107 -1
  32. package/src/charts/leaderboard-chart/types.ts +0 -2
  33. package/src/charts/line-chart/line-chart.module.scss +12 -7
  34. package/src/charts/line-chart/line-chart.tsx +32 -28
  35. package/src/charts/line-chart/private/line-chart-annotation.tsx +4 -4
  36. package/src/charts/line-chart/private/line-chart-annotations-overlay.tsx +2 -2
  37. package/src/charts/line-chart/test/line-chart.test.tsx +262 -5
  38. package/src/charts/line-chart/types.ts +4 -3
  39. package/src/charts/pie-chart/pie-chart.tsx +12 -14
  40. package/src/charts/pie-chart/test/pie-chart.test.tsx +73 -1
  41. package/src/charts/pie-semi-circle-chart/pie-semi-circle-chart.module.scss +2 -2
  42. package/src/charts/pie-semi-circle-chart/pie-semi-circle-chart.tsx +12 -14
  43. package/src/charts/private/{single-chart-context/single-chart-context.tsx → chart-instance-context/chart-instance-context.ts} +1 -5
  44. package/src/charts/private/chart-instance-context/index.ts +3 -0
  45. package/src/charts/private/{single-chart-context/use-single-chart-context.ts → chart-instance-context/use-chart-instance-context.ts} +1 -3
  46. package/src/charts/private/svg-empty-state/get-all-hidden-message.ts +41 -0
  47. package/src/charts/private/svg-empty-state/index.ts +1 -0
  48. package/src/charts/private/svg-empty-state/svg-empty-state.module.scss +1 -1
  49. package/src/charts/private/svg-empty-state/test/get-all-hidden-message.test.ts +15 -0
  50. package/src/charts/private/with-responsive/test/with-responsive.test.tsx +16 -0
  51. package/src/charts/private/with-responsive/with-responsive.tsx +18 -11
  52. package/src/charts/private/x-zoom/test/x-zoom.test.tsx +2 -2
  53. package/src/charts/private/x-zoom/x-zoom.module.scss +3 -3
  54. package/src/charts/private/x-zoom/x-zoom.tsx +2 -2
  55. package/src/components/legend/legend.tsx +4 -4
  56. package/src/components/legend/private/base-legend.module.scss +1 -1
  57. package/src/components/legend/private/base-legend.tsx +70 -19
  58. package/src/components/legend/test/legend.test.tsx +100 -4
  59. package/src/components/tooltip/accessible-tooltip.tsx +17 -4
  60. package/src/components/tooltip/base-tooltip.tsx +8 -1
  61. package/src/components/trend-indicator/test/trend-indicator.test.tsx +20 -0
  62. package/src/components/trend-indicator/trend-indicator.module.scss +4 -7
  63. package/src/components/trend-indicator/trend-indicator.tsx +3 -0
  64. package/src/hooks/index.ts +1 -1
  65. package/src/hooks/test/use-xychart-theme-provider-override.test.tsx +28 -0
  66. package/src/hooks/test/use-xychart-theme-style-reads.test.tsx +19 -13
  67. package/src/hooks/test/use-xychart-theme.test.tsx +25 -0
  68. package/src/hooks/{use-interactive-legend-data.ts → use-legend-visibility-data.ts} +29 -30
  69. package/src/hooks/use-xychart-theme.ts +6 -4
  70. package/src/index.ts +12 -3
  71. package/src/providers/chart-context/global-charts-provider.tsx +127 -30
  72. package/src/providers/chart-context/hooks/use-default-hidden-series.ts +47 -0
  73. package/src/providers/chart-context/private/theme-override-vars.ts +87 -0
  74. package/src/providers/chart-context/private/with-catalog-pointers.ts +50 -0
  75. package/src/providers/chart-context/test/chart-context.test.tsx +142 -40
  76. package/src/providers/chart-context/test/chart-scope-class.test.tsx +19 -0
  77. package/src/providers/chart-context/test/sparse-theme.test.ts +35 -0
  78. package/src/providers/chart-context/test/theme-override-vars-guard.test.tsx +29 -0
  79. package/src/providers/chart-context/test/theme-override-vars.test.ts +118 -0
  80. package/src/providers/chart-context/test/use-default-hidden-series-paint.test.tsx +56 -0
  81. package/src/providers/chart-context/test/use-default-hidden-series.ssr.test.tsx +39 -0
  82. package/src/providers/chart-context/test/use-default-hidden-series.test.tsx +222 -0
  83. package/src/providers/chart-context/test/with-catalog-pointers.test.ts +47 -0
  84. package/src/providers/chart-context/themes.ts +18 -27
  85. package/src/providers/chart-context/types.ts +7 -4
  86. package/src/providers/chart-scope/chart-scope-context.ts +8 -0
  87. package/src/providers/chart-scope/index.ts +3 -0
  88. package/src/providers/chart-scope/test/chart-scope.test.tsx +24 -0
  89. package/src/providers/chart-scope/test/use-standalone-scope-class.test.tsx +20 -0
  90. package/src/providers/chart-scope/use-chart-scope-element.ts +9 -0
  91. package/src/providers/chart-scope/use-standalone-scope-class.ts +13 -0
  92. package/src/providers/index.ts +1 -0
  93. package/src/styles/chart-scope-class.ts +6 -0
  94. package/src/styles/chart-scope.scss +83 -0
  95. package/src/styles/test/chart-scope.test.ts +165 -0
  96. package/src/styles/test/wpds-fallbacks.test.ts +131 -0
  97. package/src/types.ts +12 -34
  98. package/src/charts/private/grid-control/grid-control.module.scss +0 -8
  99. package/src/charts/private/grid-control/grid-control.tsx +0 -26
  100. package/src/charts/private/grid-control/index.ts +0 -1
  101. package/src/charts/private/grid-control/test/grid-control.test.tsx +0 -56
  102. package/src/charts/private/single-chart-context/index.ts +0 -8
@@ -4,17 +4,22 @@
4
4
  overflow: visible;
5
5
  }
6
6
 
7
+ // Keep the collapsed state in `from` and never on the element: a dropped
8
+ // animation then fails visible. `both`, not `forwards`, for backwards fill.
7
9
  &--animated rect {
8
10
  transform-origin: bottom;
9
11
  transform-box: fill-box;
10
- transform: scaleY(0);
11
12
  animation:
12
- rise var(--wpds-motion-duration-xl, 400ms)
13
- var(--wpds-motion-easing-expressive, cubic-bezier(0.25, 0, 0, 1)) forwards;
13
+ rise var(--a8c-charts-motion-duration-entrance)
14
+ var(--a8c-charts-motion-easing-entrance) both;
14
15
  }
15
16
 
16
17
  @keyframes rise {
17
18
 
19
+ from {
20
+ transform: scaleY(0);
21
+ }
22
+
18
23
  to {
19
24
  transform: scaleY(1);
20
25
  }
@@ -23,14 +28,17 @@
23
28
  &--animated-horizontal rect {
24
29
  transform-origin: left;
25
30
  transform-box: fill-box;
26
- transform: scaleX(0);
27
31
  animation:
28
- stretch var(--wpds-motion-duration-xl, 400ms)
29
- var(--wpds-motion-easing-expressive, cubic-bezier(0.25, 0, 0, 1)) forwards;
32
+ stretch var(--a8c-charts-motion-duration-entrance)
33
+ var(--a8c-charts-motion-easing-entrance) both;
30
34
  }
31
35
 
32
36
  @keyframes stretch {
33
37
 
38
+ from {
39
+ transform: scaleX(0);
40
+ }
41
+
34
42
  to {
35
43
  transform: scaleX(1);
36
44
  }
@@ -20,11 +20,12 @@ import {
20
20
  useGlobalChartsContext,
21
21
  GlobalChartsContext,
22
22
  } from '../../providers';
23
+ import { useDefaultHiddenSeries } from '../../providers/chart-context/hooks/use-default-hidden-series';
23
24
  import { attachSubComponents } from '../../utils';
24
25
  import { useChartChildren } from '../private/chart-composition';
26
+ import { ChartInstanceContext } from '../private/chart-instance-context';
25
27
  import { ChartLayout } from '../private/chart-layout';
26
- import { SingleChartContext } from '../private/single-chart-context';
27
- import { SvgEmptyState } from '../private/svg-empty-state';
28
+ import { getAllHiddenMessage, SvgEmptyState } from '../private/svg-empty-state';
28
29
  import { withResponsive } from '../private/with-responsive';
29
30
  import styles from './bar-chart.module.scss';
30
31
  import {
@@ -42,13 +43,14 @@ import type {
42
43
  DataPointDate,
43
44
  SeriesData,
44
45
  SeriesChartLegendConfig,
46
+ SeriesVisibilityProps,
45
47
  Optional,
46
48
  } from '../../types';
47
49
  import type { RenderTooltipParams } from '../../visx/types';
48
50
  import type { ResponsiveConfig } from '../private/with-responsive';
49
51
  import type { FC, ReactNode, ComponentType } from 'react';
50
52
 
51
- export interface BarChartProps extends BaseChartProps< SeriesData[] > {
53
+ export interface BarChartProps extends BaseChartProps< SeriesData[] >, SeriesVisibilityProps {
52
54
  /**
53
55
  * Legend configuration. Supports `collapseGroups` on top of the shared options.
54
56
  */
@@ -122,6 +124,7 @@ const BarChartInternal: FC< BarChartProps > = ( {
122
124
  orientation = 'vertical',
123
125
  withPatterns = false,
124
126
  showZeroValues = false,
127
+ defaultHiddenSeries,
125
128
  animation,
126
129
  children,
127
130
  gap = 'md',
@@ -130,6 +133,11 @@ const BarChartInternal: FC< BarChartProps > = ( {
130
133
  const legendCollapseGroups = legend.collapseGroups ?? false;
131
134
  const horizontal = orientation === 'horizontal';
132
135
  const chartId = useChartId( providedChartId );
136
+ const hiddenSeries = useDefaultHiddenSeries( chartId, defaultHiddenSeries );
137
+ const isSeriesVisible = useCallback(
138
+ ( seriesLabel: string ) => ! hiddenSeries.has( seriesLabel ),
139
+ [ hiddenSeries ]
140
+ );
133
141
  const theme = useXYChartTheme( data );
134
142
 
135
143
  const dataSorted = useChartDataTransform( data );
@@ -148,14 +156,14 @@ const BarChartInternal: FC< BarChartProps > = ( {
148
156
  );
149
157
  const legendItems = useChartLegendItems( dataSorted, legendOptions );
150
158
 
151
- const { getElementStyles, isSeriesVisible } = useGlobalChartsContext();
159
+ const { getElementStyles } = useGlobalChartsContext();
152
160
 
153
161
  // A hidden series is unmounted, so it is not on the band scale either — the
154
- // axis has to choose its tick values from what is left.
162
+ // axis has to choose its tick values from what is left. Visibility is owned by
163
+ // the provider, whether it changed through the legend or programmatically.
155
164
  const isSeriesRendered = useCallback(
156
- ( series: SeriesData ) =>
157
- ! chartId || ! legendInteractive || isSeriesVisible( chartId, series.label ),
158
- [ chartId, legendInteractive, isSeriesVisible ]
165
+ ( series: SeriesData ) => isSeriesVisible( series.label ),
166
+ [ isSeriesVisible ]
159
167
  );
160
168
 
161
169
  const chartOptions = useBarChartOptions(
@@ -198,7 +206,7 @@ const BarChartInternal: FC< BarChartProps > = ( {
198
206
  totalPoints,
199
207
  } );
200
208
 
201
- // Add visibility information to series when using interactive legends
209
+ // Add visibility information from the shared legend state.
202
210
  const seriesWithVisibility = useMemo(
203
211
  () =>
204
212
  dataWithVisibleZeros.map( ( series, index ) => ( {
@@ -514,9 +522,10 @@ const BarChartInternal: FC< BarChartProps > = ( {
514
522
  );
515
523
 
516
524
  return (
517
- <SingleChartContext.Provider
525
+ <ChartInstanceContext.Provider
518
526
  value={ {
519
527
  chartId,
528
+ isSeriesVisible,
520
529
  chartWidth: width,
521
530
  chartHeight: measuredChartHeight || 0,
522
531
  } }
@@ -606,10 +615,7 @@ const BarChartInternal: FC< BarChartProps > = ( {
606
615
  width={ width }
607
616
  height={ chartHeight }
608
617
  >
609
- { __(
610
- 'All series are hidden. Click legend items to show data.',
611
- 'jetpack-charts'
612
- ) }
618
+ { getAllHiddenMessage( legendInteractive, 'series' ) }
613
619
  </SvgEmptyState>
614
620
  ) : null }
615
621
 
@@ -673,7 +679,7 @@ const BarChartInternal: FC< BarChartProps > = ( {
673
679
  );
674
680
  } }
675
681
  </ChartLayout>
676
- </SingleChartContext.Provider>
682
+ </ChartInstanceContext.Provider>
677
683
  );
678
684
  };
679
685
 
@@ -1,8 +1,10 @@
1
- import { render, renderHook, screen, within } from '@testing-library/react';
1
+ import { render, renderHook, screen, within, act } from '@testing-library/react';
2
2
  import userEvent from '@testing-library/user-event';
3
3
  import { GlobalChartsProvider } from '../../../providers';
4
- import BarChart from '../bar-chart';
4
+ import { useGlobalChartsContext } from '../../../providers/chart-context/hooks/use-global-charts-context';
5
+ import BarChart, { BarChartUnresponsive } from '../bar-chart';
5
6
  import { useBarChartOptions } from '../private';
7
+ import type { GlobalChartsContextValue } from '../../../providers/chart-context/types';
6
8
  import type { SeriesData } from '../../../types';
7
9
 
8
10
  // Mock useElementSize to return non-zero dimensions in jsdom so charts render
@@ -1017,6 +1019,64 @@ describe( 'BarChart', () => {
1017
1019
  expect( screen.queryByTestId( 'chart-tooltip-0' ) ).not.toBeInTheDocument();
1018
1020
  } );
1019
1021
 
1022
+ test( 'keeps the tooltip open once the chart re-renders under it', async () => {
1023
+ // visx hides its tooltip on a debounce and cancels only the most recently
1024
+ // scheduled hide, so anything that re-runs the tooltip effect while nothing
1025
+ // is shown leaves a hide pending that lands on the next tooltip. Seeding a
1026
+ // hidden series re-renders the chart right after mount, which is exactly
1027
+ // that shape.
1028
+ jest.useFakeTimers();
1029
+
1030
+ try {
1031
+ const user = userEvent.setup( { advanceTimers: jest.advanceTimersByTime } );
1032
+ renderWithTheme( {
1033
+ withTooltips: true,
1034
+ defaultHiddenSeries: [ 'Series B' ],
1035
+ data: [
1036
+ {
1037
+ label: 'Series A',
1038
+ data: [
1039
+ { date: new Date( '2024-01-01' ), value: 10, label: 'Jan 1' },
1040
+ { date: new Date( '2024-01-02' ), value: 20, label: 'Jan 2' },
1041
+ ],
1042
+ options: {},
1043
+ },
1044
+ {
1045
+ label: 'Series B',
1046
+ data: [
1047
+ { date: new Date( '2024-01-01' ), value: 15, label: 'Jan 1' },
1048
+ { date: new Date( '2024-01-02' ), value: 25, label: 'Jan 2' },
1049
+ ],
1050
+ options: {},
1051
+ },
1052
+ ],
1053
+ } );
1054
+
1055
+ const chart = screen.getByRole( 'grid', { name: /bar chart/i } );
1056
+ chart.focus();
1057
+
1058
+ await user.keyboard( '{ArrowRight}' );
1059
+ expect( screen.getByTestId( 'chart-tooltip-0' ) ).toHaveTextContent( 'Series A' );
1060
+
1061
+ // Well past any pending hide.
1062
+ await act( async () => {
1063
+ jest.advanceTimersByTime( 5000 );
1064
+ } );
1065
+
1066
+ expect( screen.getByTestId( 'chart-tooltip-0' ) ).toBeInTheDocument();
1067
+
1068
+ // Leaving navigation still closes it.
1069
+ await user.keyboard( '{Escape}' );
1070
+ await act( async () => {
1071
+ jest.advanceTimersByTime( 5000 );
1072
+ } );
1073
+
1074
+ expect( screen.queryByTestId( 'chart-tooltip-0' ) ).not.toBeInTheDocument();
1075
+ } finally {
1076
+ jest.useRealTimers();
1077
+ }
1078
+ } );
1079
+
1020
1080
  test( 'left arrow key navigates to previous data point', async () => {
1021
1081
  const user = userEvent.setup();
1022
1082
  renderWithTheme( {
@@ -1918,6 +1978,133 @@ describe( 'BarChart', () => {
1918
1978
  screen.getByText( /all series are hidden.*click legend items to show data/i )
1919
1979
  ).toBeInTheDocument();
1920
1980
  } );
1981
+
1982
+ it( 'hides a series programmatically when the legend is not interactive', () => {
1983
+ let context: GlobalChartsContextValue;
1984
+ const Grab = () => {
1985
+ context = useGlobalChartsContext();
1986
+ return null;
1987
+ };
1988
+
1989
+ render(
1990
+ <GlobalChartsProvider>
1991
+ <Grab />
1992
+ <BarChartUnresponsive
1993
+ width={ 500 }
1994
+ height={ 300 }
1995
+ showLegend={ true }
1996
+ legend={ { interactive: false } }
1997
+ chartId="test-programmatic-bar"
1998
+ data={ [
1999
+ {
2000
+ label: 'Series A',
2001
+ data: [ { date: new Date( '2024-01-01' ), value: 10, label: 'Jan 1' } ],
2002
+ options: {},
2003
+ },
2004
+ {
2005
+ label: 'Series B',
2006
+ data: [ { date: new Date( '2024-01-01' ), value: 20, label: 'Jan 1' } ],
2007
+ options: {},
2008
+ },
2009
+ ] }
2010
+ />
2011
+ </GlobalChartsProvider>
2012
+ );
2013
+
2014
+ act( () => {
2015
+ context.toggleSeriesVisibility( 'test-programmatic-bar', 'Series A' );
2016
+ context.toggleSeriesVisibility( 'test-programmatic-bar', 'Series B' );
2017
+ } );
2018
+
2019
+ expect( screen.getByText( /all series are hidden/i ) ).toBeInTheDocument();
2020
+ } );
2021
+
2022
+ it( 'omits the click instruction when the legend cannot be clicked', () => {
2023
+ let context: GlobalChartsContextValue;
2024
+ const Grab = () => {
2025
+ context = useGlobalChartsContext();
2026
+ return null;
2027
+ };
2028
+
2029
+ render(
2030
+ <GlobalChartsProvider>
2031
+ <Grab />
2032
+ <BarChartUnresponsive
2033
+ width={ 500 }
2034
+ height={ 300 }
2035
+ showLegend={ true }
2036
+ legend={ { interactive: false } }
2037
+ chartId="test-empty-copy-bar"
2038
+ data={ [
2039
+ {
2040
+ label: 'Series A',
2041
+ data: [ { date: new Date( '2024-01-01' ), value: 10, label: 'Jan 1' } ],
2042
+ options: {},
2043
+ },
2044
+ ] }
2045
+ />
2046
+ </GlobalChartsProvider>
2047
+ );
2048
+
2049
+ act( () => {
2050
+ context.toggleSeriesVisibility( 'test-empty-copy-bar', 'Series A' );
2051
+ } );
2052
+
2053
+ expect( screen.getByText( 'All series are hidden.' ) ).toBeInTheDocument();
2054
+ expect( screen.queryByText( /click legend items/i ) ).not.toBeInTheDocument();
2055
+ } );
2056
+
2057
+ it( 'still renders the other series when only one is hidden programmatically', () => {
2058
+ // A test that hides every series would pass even if the chart still forced
2059
+ // all series visible right up until `allSeriesHidden` short-circuited it —
2060
+ // that shape of test masked a real bug in a sibling chart. Hiding exactly
2061
+ // one of two series exercises the partial-hide render path: the bar count
2062
+ // only drops to one if the hidden series' `BarSeries` is actually excluded
2063
+ // from the `BarGroup`, not merely rendered with zero opacity.
2064
+ let context: GlobalChartsContextValue;
2065
+ const Grab = () => {
2066
+ context = useGlobalChartsContext();
2067
+ return null;
2068
+ };
2069
+
2070
+ render(
2071
+ <GlobalChartsProvider>
2072
+ <Grab />
2073
+ <BarChartUnresponsive
2074
+ width={ 500 }
2075
+ height={ 300 }
2076
+ showLegend={ true }
2077
+ legend={ { interactive: false } }
2078
+ chartId="test-programmatic-partial-bar"
2079
+ data={ [
2080
+ {
2081
+ label: 'Series A',
2082
+ data: [ { date: new Date( '2024-01-01' ), value: 10, label: 'Jan 1' } ],
2083
+ options: {},
2084
+ },
2085
+ {
2086
+ label: 'Series B',
2087
+ data: [ { date: new Date( '2024-01-01' ), value: 20, label: 'Jan 1' } ],
2088
+ options: {},
2089
+ },
2090
+ ] }
2091
+ />
2092
+ </GlobalChartsProvider>
2093
+ );
2094
+
2095
+ // eslint-disable-next-line testing-library/no-node-access
2096
+ const svgElement = screen.getByRole( 'grid', { name: /bar chart/i } ).querySelector( 'svg' );
2097
+ // eslint-disable-next-line testing-library/no-node-access
2098
+ expect( svgElement?.querySelectorAll( '.visx-bar-group rect' ) ).toHaveLength( 2 );
2099
+
2100
+ act( () => {
2101
+ context.toggleSeriesVisibility( 'test-programmatic-partial-bar', 'Series B' );
2102
+ } );
2103
+
2104
+ expect( screen.queryByText( /all series are hidden/i ) ).not.toBeInTheDocument();
2105
+ // eslint-disable-next-line testing-library/no-node-access
2106
+ expect( svgElement?.querySelectorAll( '.visx-bar-group rect' ) ).toHaveLength( 1 );
2107
+ } );
1921
2108
  } );
1922
2109
 
1923
2110
  describe( 'Legend group collapsing', () => {
@@ -1996,4 +2183,70 @@ describe( 'BarChart', () => {
1996
2183
  ).toBeInTheDocument();
1997
2184
  } );
1998
2185
  } );
2186
+
2187
+ describe( 'defaultHiddenSeries', () => {
2188
+ it( 'renders a series hidden when named in defaultHiddenSeries', () => {
2189
+ render(
2190
+ <GlobalChartsProvider>
2191
+ <BarChartUnresponsive
2192
+ width={ 500 }
2193
+ height={ 300 }
2194
+ showLegend={ true }
2195
+ legend={ { interactive: true } }
2196
+ chartId="test-default-hidden-bar"
2197
+ defaultHiddenSeries={ [ 'Series B' ] }
2198
+ data={ [
2199
+ {
2200
+ label: 'Series A',
2201
+ data: [ { date: new Date( '2024-01-01' ), value: 10, label: 'Jan 1' } ],
2202
+ options: {},
2203
+ },
2204
+ {
2205
+ label: 'Series B',
2206
+ data: [ { date: new Date( '2024-01-01' ), value: 20, label: 'Jan 1' } ],
2207
+ options: {},
2208
+ },
2209
+ ] }
2210
+ />
2211
+ </GlobalChartsProvider>
2212
+ );
2213
+
2214
+ const items = screen.getAllByRole( 'button' );
2215
+ expect( items[ 0 ] ).toHaveAttribute( 'aria-pressed', 'true' );
2216
+ expect( items[ 1 ] ).toHaveAttribute( 'aria-pressed', 'false' );
2217
+ } );
2218
+
2219
+ it( 'lets the user reveal a series seeded hidden', async () => {
2220
+ const user = userEvent.setup();
2221
+
2222
+ render(
2223
+ <GlobalChartsProvider>
2224
+ <BarChartUnresponsive
2225
+ width={ 500 }
2226
+ height={ 300 }
2227
+ showLegend={ true }
2228
+ legend={ { interactive: true } }
2229
+ chartId="test-default-hidden-reveal-bar"
2230
+ defaultHiddenSeries={ [ 'Series B' ] }
2231
+ data={ [
2232
+ {
2233
+ label: 'Series A',
2234
+ data: [ { date: new Date( '2024-01-01' ), value: 10, label: 'Jan 1' } ],
2235
+ options: {},
2236
+ },
2237
+ {
2238
+ label: 'Series B',
2239
+ data: [ { date: new Date( '2024-01-01' ), value: 20, label: 'Jan 1' } ],
2240
+ options: {},
2241
+ },
2242
+ ] }
2243
+ />
2244
+ </GlobalChartsProvider>
2245
+ );
2246
+
2247
+ await user.click( screen.getAllByRole( 'button' )[ 1 ] );
2248
+
2249
+ expect( screen.getAllByRole( 'button' )[ 1 ] ).toHaveAttribute( 'aria-pressed', 'true' );
2250
+ } );
2251
+ } );
1999
2252
  } );
@@ -12,11 +12,11 @@
12
12
 
13
13
  .main-rate {
14
14
  overflow: hidden;
15
- color: var(--a8c-charts-color-label, var(--wpds-color-foreground-content-neutral, #1e1e1e));
15
+ color: var(--a8c-charts-color-label);
16
16
  text-overflow: ellipsis;
17
- font-size: var(--wpds-typography-font-size-xl, 18px);
17
+ font-size: var(--wpds-typography-font-size-xl, 20px);
18
18
  font-style: normal;
19
- font-weight: var(--wpds-typography-font-weight-emphasis, 499);
19
+ font-weight: var(--wpds-typography-font-weight-emphasis, 600);
20
20
  line-height: var(--wpds-typography-line-height-sm, 20px);
21
21
  margin: 0;
22
22
  }
@@ -26,7 +26,7 @@
26
26
  text-overflow: ellipsis;
27
27
  font-size: var(--wpds-typography-font-size-md, 13px);
28
28
  font-style: normal;
29
- font-weight: var(--wpds-typography-font-weight-emphasis, 499);
29
+ font-weight: var(--wpds-typography-font-weight-emphasis, 600);
30
30
  line-height: var(--wpds-typography-line-height-sm, 20px);
31
31
  margin: 0;
32
32
  }
@@ -54,7 +54,7 @@
54
54
  }
55
55
 
56
56
  .step-label {
57
- color: var(--a8c-charts-color-label-secondary, var(--wpds-color-foreground-content-neutral-weak, #707070));
57
+ color: var(--a8c-charts-color-label-secondary);
58
58
  font-size: var(--wpds-typography-font-size-sm, 12px);
59
59
  font-weight: var(--wpds-typography-font-weight-default, 400);
60
60
  line-height: var(--wpds-typography-line-height-xs, 16px);
@@ -64,15 +64,15 @@
64
64
  }
65
65
 
66
66
  .step-rate {
67
- color: var(--a8c-charts-color-label, var(--wpds-color-foreground-content-neutral, #1e1e1e));
67
+ color: var(--a8c-charts-color-label);
68
68
  font-size: var(--wpds-typography-font-size-md, 13px);
69
- font-weight: var(--wpds-typography-font-weight-emphasis, 499);
69
+ font-weight: var(--wpds-typography-font-weight-emphasis, 600);
70
70
  line-height: var(--wpds-typography-line-height-xs, 16px);
71
71
  }
72
72
 
73
73
  .bar-container {
74
74
  flex: 1;
75
- border-radius: var(--wpds-border-radius-md, 4px);
75
+ border-radius: var(--a8c-charts-border-radius-bar);
76
76
  position: relative;
77
77
  cursor: pointer;
78
78
  }
@@ -80,19 +80,24 @@
80
80
  .funnel-bar {
81
81
  width: 100%;
82
82
  min-height: 4px;
83
- border-radius: var(--wpds-border-radius-md, 4px) var(--wpds-border-radius-md, 4px) 0 0;
83
+ border-radius: var(--a8c-charts-border-radius-bar) var(--a8c-charts-border-radius-bar) 0 0;
84
84
 
85
+ // Keep the collapsed state in `from` and never on the element: a dropped
86
+ // animation then fails visible. `both`, not `forwards`, for backwards fill.
85
87
  &--animated {
86
88
  transform-origin: bottom;
87
89
  transform-box: fill-box;
88
- transform: scaleY(0);
89
90
  animation:
90
- stretch var(--wpds-motion-duration-xl, 400ms)
91
- var(--wpds-motion-easing-expressive, cubic-bezier(0.25, 0, 0, 1)) forwards;
91
+ stretch var(--a8c-charts-motion-duration-entrance)
92
+ var(--a8c-charts-motion-easing-entrance) both;
92
93
  }
93
94
 
94
95
  @keyframes stretch {
95
96
 
97
+ from {
98
+ transform: scaleY(0);
99
+ }
100
+
96
101
  to {
97
102
  transform: scaleY(1);
98
103
  }
@@ -100,7 +105,7 @@
100
105
  }
101
106
 
102
107
  .tooltip-wrapper {
103
- background: var(--a8c-charts-color-background, var(--wpds-color-background-surface-neutral-strong, #fff));
108
+ background: var(--a8c-charts-color-surface);
104
109
 
105
110
  // Override .visx-tooltip inline styles.
106
111
  border-radius: var(--wpds-border-radius-md, 4px) !important;
@@ -110,7 +115,7 @@
110
115
  }
111
116
 
112
117
  .tooltip-title {
113
- color: var(--a8c-charts-color-label, var(--wpds-color-foreground-content-neutral, #1e1e1e));
118
+ color: var(--a8c-charts-color-label);
114
119
  font-size: var(--wpds-typography-font-size-sm, 12px);
115
120
  font-style: normal;
116
121
  font-weight: var(--wpds-typography-font-weight-default, 400);
@@ -118,15 +123,15 @@
118
123
  }
119
124
 
120
125
  .tooltip-content {
121
- color: var(--a8c-charts-color-label, var(--wpds-color-foreground-content-neutral, #1e1e1e));
126
+ color: var(--a8c-charts-color-label);
122
127
  font-size: var(--wpds-typography-font-size-md, 13px);
123
128
  font-style: normal;
124
- font-weight: var(--wpds-typography-font-weight-emphasis, 499);
129
+ font-weight: var(--wpds-typography-font-weight-emphasis, 600);
125
130
  line-height: var(--wpds-typography-line-height-sm, 20px);
126
131
  }
127
132
 
128
133
  .empty-state {
129
134
  text-align: center;
130
- color: var(--a8c-charts-color-label-secondary, var(--wpds-color-foreground-content-neutral-weak, #707070));
131
- font-size: var(--wpds-typography-font-size-lg, 16px);
135
+ color: var(--a8c-charts-color-label-secondary);
136
+ font-size: var(--wpds-typography-font-size-lg, 15px);
132
137
  }