@coinbase/cds-mcp-server 8.52.0 → 8.52.1

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.
@@ -144,11 +144,7 @@ You can have different area styles for each series.
144
144
 
145
145
  ### Animations
146
146
 
147
- You can configure chart transitions using the `transitions` prop.
148
-
149
- #### Customized Transitions
150
-
151
- You can pass in a custom spring based transition to your `AreaChart` for a custom update transition.
147
+ You can configure chart transitions using the `transitions` prop. Also, you can toggle animations by setting `animate` to `true` or `false`.
152
148
 
153
149
  ```jsx live
154
150
  function AnimatedStackedAreas() {
@@ -209,7 +205,7 @@ function AnimatedStackedAreas() {
209
205
  <DottedArea {...props} baselineOpacity={1} peakOpacity={1} />
210
206
  ));
211
207
 
212
- function AnimatedChart() {
208
+ function AnimatedChart(props) {
213
209
  const [data, setData] = useState(generateInitialData);
214
210
 
215
211
  useEffect(() => {
@@ -253,125 +249,36 @@ function AnimatedStackedAreas() {
253
249
  tickLabelFormatter: () => '',
254
250
  domain: { min: 0, max: domainLimit },
255
251
  }}
252
+ {...props}
256
253
  />
257
254
  );
258
255
  }
259
256
 
260
- return <AnimatedChart />;
261
- }
262
- ```
263
-
264
- #### Disable Animations
265
-
266
- You can also disable animations by setting the `animate` prop to `false`.
267
-
268
- ```jsx live
269
- function AnimatedStackedAreas() {
270
- const dataCount = 20;
271
- const minYValue = 5000;
272
- const maxDataOffset = 15000;
273
- const minStepOffset = 2500;
274
- const maxStepOffset = 10000;
275
- const updateInterval = 500;
276
- const seriesSpacing = 2000;
277
- const myTransition = { type: 'spring', stiffness: 700, damping: 20 };
278
-
279
- const seriesConfig = [
280
- { id: 'red', label: 'Red', color: 'rgb(var(--red40))' },
281
- { id: 'orange', label: 'Orange', color: 'rgb(var(--orange40))' },
282
- { id: 'yellow', label: 'Yellow', color: 'rgb(var(--yellow40))' },
283
- { id: 'green', label: 'Green', color: 'rgb(var(--green40))' },
284
- { id: 'blue', label: 'Blue', color: 'rgb(var(--blue40))' },
285
- { id: 'indigo', label: 'Indigo', color: 'rgb(var(--indigo40))' },
286
- { id: 'purple', label: 'Purple', color: 'rgb(var(--purple40))' },
287
- ];
288
-
289
- const domainLimit = maxDataOffset + seriesConfig.length * seriesSpacing;
290
-
291
- function generateNextValue(previousValue) {
292
- const range = maxStepOffset - minStepOffset;
293
- const offset = Math.random() * range + minStepOffset;
294
-
295
- let direction;
296
- if (previousValue >= maxDataOffset) {
297
- direction = -1;
298
- } else if (previousValue <= minYValue) {
299
- direction = 1;
300
- } else {
301
- direction = Math.random() < 0.5 ? -1 : 1;
302
- }
303
-
304
- let newValue = previousValue + offset * direction;
305
- newValue = Math.max(minYValue, Math.min(maxDataOffset, newValue));
306
- return newValue;
307
- }
308
-
309
- function generateInitialData() {
310
- const data = [];
311
-
312
- let previousValue = minYValue + Math.random() * (maxDataOffset - minYValue);
313
- data.push(previousValue);
314
-
315
- for (let i = 1; i < dataCount; i++) {
316
- const newValue = generateNextValue(previousValue);
317
- data.push(newValue);
318
- previousValue = newValue;
319
- }
320
-
321
- return data;
322
- }
323
-
324
- const MemoizedDottedArea = memo((props) => (
325
- <DottedArea {...props} baselineOpacity={1} peakOpacity={1} />
326
- ));
327
-
328
- function AnimatedChart() {
329
- const [data, setData] = useState(generateInitialData);
330
-
331
- useEffect(() => {
332
- const intervalId = setInterval(() => {
333
- setData((currentData) => {
334
- const lastValue = currentData[currentData.length - 1] ?? 0;
335
- const newValue = generateNextValue(lastValue);
336
-
337
- return [...currentData.slice(1), newValue];
338
- });
339
- }, updateInterval);
340
-
341
- return () => clearInterval(intervalId);
342
- }, []);
343
-
344
- const series = seriesConfig.map((config, index) => ({
345
- id: config.id,
346
- label: config.label,
347
- color: config.color,
348
- // First series gets animated data, others get constant height
349
- data: index === 0 ? data : Array(dataCount).fill(seriesSpacing),
350
- }));
257
+ function AnimatedChartExample() {
258
+ const animatedStates = [
259
+ { id: 'on', label: 'On' },
260
+ { id: 'off', label: 'Off' },
261
+ ];
262
+ const [animatedState, setAnimatedState] = useState(animatedStates[0]);
351
263
 
352
264
  return (
353
- <AreaChart
354
- animate={false}
355
- overflow="visible"
356
- stacked
357
- height={{ base: 200, tablet: 250, desktop: 300 }}
358
- series={series}
359
- type="dotted"
360
- showLines
361
- AreaComponent={MemoizedDottedArea}
362
- inset={0}
363
- showYAxis
364
- yAxis={{
365
- showGrid: true,
366
- width: 0,
367
- tickLabelFormatter: () => '',
368
- domain: { min: 0, max: domainLimit },
369
- }}
370
- />
265
+ <VStack gap={2}>
266
+ <HStack justifyContent="flex-end" gap={2} alignItems="center">
267
+ <Text as="h3" font="headline">
268
+ Animations
269
+ </Text>
270
+ <SegmentedTabs
271
+ activeTab={animatedState}
272
+ onChange={setAnimatedState}
273
+ tabs={animatedStates}
274
+ />
275
+ </HStack>
276
+ <AnimatedChart animate={animatedState.id === 'on'} />
277
+ </VStack>
371
278
  );
372
279
  }
373
280
 
374
- return <AnimatedChart />;
281
+ return <AnimatedChartExample />;
375
282
  }
376
283
  ```
377
284
 
@@ -678,6 +585,7 @@ function XAxisGradient() {
678
585
  | `inset` | `number \| Partial<ChartInset>` | No | `-` | Inset around the entire chart (outside the axes). |
679
586
  | `justifyContent` | `ResponsiveProp<left \| right \| center \| normal \| start \| end \| flex-start \| flex-end \| space-between \| space-around \| space-evenly \| stretch>` | No | `-` | - |
680
587
  | `key` | `Key \| null` | No | `-` | - |
588
+ | `layout` | `horizontal \| vertical` | No | `'vertical'` | Chart layout - describes the direction bars/areas grow. - vertical (default): Bars grow vertically. X is category axis, Y is value axis. - horizontal: Bars grow horizontally. Y is category axis, X is value axis. |
681
589
  | `left` | `ResponsiveProp<Left<string \| number>>` | No | `-` | - |
682
590
  | `legend` | `null \| string \| number \| false \| true \| ReactElement<any, string \| JSXElementConstructor<any>> \| Iterable<ReactNode> \| ReactPortal` | No | `-` | Whether to show the legend or a custom legend element. - true renders the default Legend component - A React element renders that element as the legend - false or omitted hides the legend |
683
591
  | `legendAccessibilityLabel` | `string` | No | `'Legend'` | Accessibility label for the legend group. |
@@ -731,8 +639,8 @@ function XAxisGradient() {
731
639
  | `userSelect` | `ResponsiveProp<text \| none \| all \| auto>` | No | `-` | - |
732
640
  | `visibility` | `ResponsiveProp<hidden \| visible>` | No | `-` | - |
733
641
  | `width` | `ResponsiveProp<Width<string \| number>>` | No | `-` | - |
734
- | `xAxis` | `(Partial<AxisConfigProps> & SharedProps & { bandGridLinePlacement?: AxisBandPlacement; bandTickMarkPlacement?: AxisBandPlacement \| undefined; label?: string \| undefined; labelGap?: number \| undefined; minTickLabelGap?: number \| undefined; requestedTickCount?: number \| undefined; showGrid?: boolean \| undefined; showLine?: boolean \| undefined; showTickMarks?: boolean \| undefined; tickMarkSize?: number \| undefined; ticks?: number[] \| ((value: number) => boolean) \| undefined; tickMarkLabelGap?: number \| undefined; tickInterval?: number \| undefined; tickMinStep?: number \| undefined; tickMaxStep?: number \| undefined; } & { className?: string \| undefined; classNames?: { root?: string \| undefined; label?: string \| undefined; tickLabel?: string \| undefined; gridLine?: string \| undefined; line?: string \| undefined; tickMark?: string \| undefined; } \| undefined; style?: CSSProperties \| undefined; styles?: { root?: CSSProperties \| undefined; label?: CSSProperties \| undefined; tickLabel?: CSSProperties \| undefined; gridLine?: CSSProperties \| undefined; line?: CSSProperties \| undefined; tickMark?: CSSProperties \| undefined; } \| undefined; GridLineComponent?: LineComponent \| undefined; LineComponent?: LineComponent \| undefined; TickMarkLineComponent?: LineComponent \| undefined; tickLabelFormatter?: ((value: number) => ChartTextChildren) \| undefined; TickLabelComponent?: AxisTickLabelComponent \| undefined; } & { position?: top \| bottom \| undefined; height?: number \| undefined; }) \| undefined` | No | `-` | Configuration for x-axis. Accepts axis config and axis props. To show the axis, set showXAxis to true. |
735
- | `yAxis` | `(Partial<AxisConfigProps> & SharedProps & { bandGridLinePlacement?: AxisBandPlacement; bandTickMarkPlacement?: AxisBandPlacement \| undefined; label?: string \| undefined; labelGap?: number \| undefined; minTickLabelGap?: number \| undefined; requestedTickCount?: number \| undefined; showGrid?: boolean \| undefined; showLine?: boolean \| undefined; showTickMarks?: boolean \| undefined; tickMarkSize?: number \| undefined; ticks?: number[] \| ((value: number) => boolean) \| undefined; tickMarkLabelGap?: number \| undefined; tickInterval?: number \| undefined; tickMinStep?: number \| undefined; tickMaxStep?: number \| undefined; } & { className?: string \| undefined; classNames?: { root?: string \| undefined; label?: string \| undefined; tickLabel?: string \| undefined; gridLine?: string \| undefined; line?: string \| undefined; tickMark?: string \| undefined; } \| undefined; style?: CSSProperties \| undefined; styles?: { root?: CSSProperties \| undefined; label?: CSSProperties \| undefined; tickLabel?: CSSProperties \| undefined; gridLine?: CSSProperties \| undefined; line?: CSSProperties \| undefined; tickMark?: CSSProperties \| undefined; } \| undefined; GridLineComponent?: LineComponent \| undefined; LineComponent?: LineComponent \| undefined; TickMarkLineComponent?: LineComponent \| undefined; tickLabelFormatter?: ((value: number) => ChartTextChildren) \| undefined; TickLabelComponent?: AxisTickLabelComponent \| undefined; } & { axisId?: string \| undefined; position?: left \| right \| undefined; width?: number \| undefined; }) \| undefined` | No | `-` | Configuration for y-axis. Accepts axis config and axis props. To show the axis, set showYAxis to true. |
642
+ | `xAxis` | `(Partial<CartesianAxisConfigProps> & SharedProps & { bandGridLinePlacement?: AxisBandPlacement; bandTickMarkPlacement?: AxisBandPlacement \| undefined; label?: string \| undefined; labelGap?: number \| undefined; minTickLabelGap?: number \| undefined; requestedTickCount?: number \| undefined; showGrid?: boolean \| undefined; showLine?: boolean \| undefined; showTickMarks?: boolean \| undefined; tickMarkSize?: number \| undefined; ticks?: number[] \| ((value: number) => boolean) \| undefined; tickMarkLabelGap?: number \| undefined; tickInterval?: number \| undefined; tickMinStep?: number \| undefined; tickMaxStep?: number \| undefined; } & { className?: string \| undefined; classNames?: { root?: string \| undefined; label?: string \| undefined; tickLabel?: string \| undefined; gridLine?: string \| undefined; line?: string \| undefined; tickMark?: string \| undefined; } \| undefined; style?: CSSProperties \| undefined; styles?: { root?: CSSProperties \| undefined; label?: CSSProperties \| undefined; tickLabel?: CSSProperties \| undefined; gridLine?: CSSProperties \| undefined; line?: CSSProperties \| undefined; tickMark?: CSSProperties \| undefined; } \| undefined; GridLineComponent?: LineComponent \| undefined; LineComponent?: LineComponent \| undefined; TickMarkLineComponent?: LineComponent \| undefined; tickLabelFormatter?: ((value: number) => ChartTextChildren) \| undefined; TickLabelComponent?: AxisTickLabelComponent \| undefined; } & { axisId?: string \| undefined; position?: top \| bottom \| undefined; height?: number \| undefined; }) \| undefined` | No | `-` | Configuration for x-axis. Accepts axis config and axis props. To show the axis, set showXAxis to true. |
643
+ | `yAxis` | `(Partial<CartesianAxisConfigProps> & SharedProps & { bandGridLinePlacement?: AxisBandPlacement; bandTickMarkPlacement?: AxisBandPlacement \| undefined; label?: string \| undefined; labelGap?: number \| undefined; minTickLabelGap?: number \| undefined; requestedTickCount?: number \| undefined; showGrid?: boolean \| undefined; showLine?: boolean \| undefined; showTickMarks?: boolean \| undefined; tickMarkSize?: number \| undefined; ticks?: number[] \| ((value: number) => boolean) \| undefined; tickMarkLabelGap?: number \| undefined; tickInterval?: number \| undefined; tickMinStep?: number \| undefined; tickMaxStep?: number \| undefined; } & { className?: string \| undefined; classNames?: { root?: string \| undefined; label?: string \| undefined; tickLabel?: string \| undefined; gridLine?: string \| undefined; line?: string \| undefined; tickMark?: string \| undefined; } \| undefined; style?: CSSProperties \| undefined; styles?: { root?: CSSProperties \| undefined; label?: CSSProperties \| undefined; tickLabel?: CSSProperties \| undefined; gridLine?: CSSProperties \| undefined; line?: CSSProperties \| undefined; tickMark?: CSSProperties \| undefined; } \| undefined; GridLineComponent?: LineComponent \| undefined; LineComponent?: LineComponent \| undefined; TickMarkLineComponent?: LineComponent \| undefined; tickLabelFormatter?: ((value: number) => ChartTextChildren) \| undefined; TickLabelComponent?: AxisTickLabelComponent \| undefined; } & { axisId?: string \| undefined; position?: left \| right \| undefined; width?: number \| undefined; }) \| undefined` | No | `-` | Configuration for y-axis. Accepts axis config and axis props. To show the axis, set showYAxis to true. |
736
644
  | `zIndex` | `inherit \| auto \| revert \| -moz-initial \| initial \| revert-layer \| unset` | No | `-` | - |
737
645
 
738
646
 
@@ -10,7 +10,7 @@ import { BarChart } from '@coinbase/cds-web-visualization'
10
10
 
11
11
  ## Examples
12
12
 
13
- ### Basic Example
13
+ ### Basics
14
14
 
15
15
  Bar charts are a useful component for comparing discrete categories of data.
16
16
  They are helpful for highlighting trends to users or allowing them to compare proportions at a glance.
@@ -34,6 +34,61 @@ To start, pass in a series of data to the chart.
34
34
  />
35
35
  ```
36
36
 
37
+ ### Horizontal Bars
38
+
39
+ To show horizontal bars, set `layout` to `"horizontal"`. In this layout, the Y axis becomes the categorical axis and the X axis becomes the value axis.
40
+
41
+ ```jsx live
42
+ function HorizontalBars() {
43
+ const dataset = [
44
+ { month: 'Jan', seoul: 21 },
45
+ { month: 'Feb', seoul: 28 },
46
+ { month: 'Mar', seoul: 41 },
47
+ { month: 'Apr', seoul: 73 },
48
+ { month: 'May', seoul: 99 },
49
+ { month: 'June', seoul: 144 },
50
+ { month: 'July', seoul: 319 },
51
+ { month: 'Aug', seoul: 249 },
52
+ { month: 'Sept', seoul: 131 },
53
+ { month: 'Oct', seoul: 55 },
54
+ { month: 'Nov', seoul: 48 },
55
+ { month: 'Dec', seoul: 25 },
56
+ ];
57
+
58
+ return (
59
+ <BarChart
60
+ height={400}
61
+ layout="horizontal"
62
+ series={[
63
+ {
64
+ id: 'seoul',
65
+ label: 'Seoul rainfall',
66
+ data: dataset.map((d) => d.seoul),
67
+ color: 'var(--color-accentBoldBlue)',
68
+ },
69
+ ]}
70
+ borderRadius={2}
71
+ showXAxis
72
+ showYAxis
73
+ xAxis={{
74
+ label: 'rainfall (mm)',
75
+ GridLineComponent: (props) => <SolidLine {...props} strokeWidth={1} />,
76
+ showGrid: true,
77
+ showLine: true,
78
+ showTickMarks: true,
79
+ }}
80
+ yAxis={{
81
+ position: 'left',
82
+ data: dataset.map((d) => d.month),
83
+ showLine: true,
84
+ showTickMarks: true,
85
+ bandTickMarkPlacement: 'edges',
86
+ }}
87
+ />
88
+ );
89
+ }
90
+ ```
91
+
37
92
  ### Multiple Series
38
93
 
39
94
  You can also provide multiple series of data to the chart. Series will have their bars for each data point rendered side by side.
@@ -293,7 +348,7 @@ function MonthlyGainsByAsset() {
293
348
 
294
349
  ### Border Radius
295
350
 
296
- Bars have a default border radius of `100`. You can change this by setting the `borderRadius` prop on the chart.
351
+ Bars have a default `borderRadius` of `4`. You can change this by setting the `borderRadius` prop on the chart.
297
352
 
298
353
  Stacks will only round the top corners of touching bars.
299
354
 
@@ -640,7 +695,7 @@ You can also set the `barMinSize` prop to control the minimum size for individua
640
695
  />
641
696
  ```
642
697
 
643
- #### Multiple Y Axes
698
+ #### Multiple Axes
644
699
 
645
700
  You can render bars from separate y axes in one `BarPlot`, however they aren't able to be stacked.
646
701
 
@@ -704,6 +759,69 @@ You can render bars from separate y axes in one `BarPlot`, however they aren't a
704
759
  </CartesianChart>
705
760
  ```
706
761
 
762
+ When using horizontal layout, you can use multiple x axes.
763
+
764
+ ```jsx live
765
+ <CartesianChart
766
+ layout="horizontal"
767
+ legend
768
+ height={400}
769
+ inset={{ top: 8, bottom: 8, left: 0, right: 0 }}
770
+ legendPosition="bottom"
771
+ series={[
772
+ {
773
+ id: 'revenue',
774
+ label: 'Revenue ($)',
775
+ data: [455, 520, 380, 455, 285, 235],
776
+ xAxisId: 'revenue',
777
+ color: 'var(--color-accentBoldYellow)',
778
+ },
779
+ {
780
+ id: 'profitMargin',
781
+ label: 'Profit Margin (%)',
782
+ data: [23, 20, 16, 38, 12, 9],
783
+ xAxisId: 'profitMargin',
784
+ color: 'var(--color-fgPositive)',
785
+ },
786
+ ]}
787
+ xAxis={[
788
+ {
789
+ id: 'revenue',
790
+ domain: { min: 0 },
791
+ },
792
+ {
793
+ id: 'profitMargin',
794
+ domain: { min: 0, max: 100 },
795
+ },
796
+ ]}
797
+ yAxis={{
798
+ data: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
799
+ scaleType: 'band',
800
+ }}
801
+ >
802
+ <YAxis showLine showTickMarks position="left" />
803
+ <XAxis
804
+ showGrid
805
+ showLine
806
+ showTickMarks
807
+ axisId="revenue"
808
+ position="top"
809
+ requestedTickCount={5}
810
+ height={60}
811
+ tickLabelFormatter={(value) => `$${value}k`}
812
+ />
813
+ <XAxis
814
+ showLine
815
+ showTickMarks
816
+ axisId="profitMargin"
817
+ position="bottom"
818
+ requestedTickCount={5}
819
+ tickLabelFormatter={(value) => `${value}%`}
820
+ />
821
+ <BarPlot />
822
+ </CartesianChart>
823
+ ```
824
+
707
825
  #### Custom Components
708
826
 
709
827
  ##### Outlined Stacks
@@ -770,11 +888,7 @@ function MonthlyRewards() {
770
888
 
771
889
  ### Animations
772
890
 
773
- You can configure chart transitions using the `transitions` prop.
774
-
775
- #### Customized Transitions
776
-
777
- You can pass in a custom spring based transition to your `BarChart` for a custom update transition.
891
+ You can configure chart transitions using the `transitions` prop. Also, you can toggle animations by setting `animate` to `true` or `false`.
778
892
 
779
893
  ```jsx live
780
894
  function AnimatedStackedBars() {
@@ -831,7 +945,7 @@ function AnimatedStackedBars() {
831
945
  return data;
832
946
  }
833
947
 
834
- function AnimatedChart() {
948
+ function AnimatedChart(props) {
835
949
  const [data, setData] = useState(generateInitialData);
836
950
 
837
951
  useEffect(() => {
@@ -871,115 +985,36 @@ function AnimatedStackedBars() {
871
985
  tickLabelFormatter: () => '',
872
986
  domain: { min: 0, max: domainLimit },
873
987
  }}
988
+ {...props}
874
989
  />
875
990
  );
876
991
  }
877
992
 
878
- return <AnimatedChart />;
879
- }
880
- ```
881
-
882
- #### Disable Animations
883
-
884
- You can also disable animations by setting the `animate` prop to `false`.
885
-
886
- ```jsx live
887
- function AnimatedStackedBars() {
888
- const dataCount = 12;
889
- const minValue = 20;
890
- const maxValue = 100;
891
- const minStep = 10;
892
- const maxStep = 40;
893
- const updateInterval = 600;
894
- const seriesSpacing = 30;
895
-
896
- const seriesConfig = [
897
- { id: 'red', label: 'Red', color: 'rgb(var(--red40))' },
898
- { id: 'orange', label: 'Orange', color: 'rgb(var(--orange40))' },
899
- { id: 'yellow', label: 'Yellow', color: 'rgb(var(--yellow40))' },
900
- { id: 'green', label: 'Green', color: 'rgb(var(--green40))' },
901
- { id: 'blue', label: 'Blue', color: 'rgb(var(--blue40))' },
902
- { id: 'indigo', label: 'Indigo', color: 'rgb(var(--indigo40))' },
903
- { id: 'purple', label: 'Purple', color: 'rgb(var(--purple40))' },
904
- ];
905
-
906
- const domainLimit = maxValue + seriesConfig.length * seriesSpacing;
907
-
908
- function generateNextValue(previousValue) {
909
- const range = maxStep - minStep;
910
- const offset = Math.random() * range + minStep;
911
-
912
- let direction;
913
- if (previousValue >= maxValue) {
914
- direction = -1;
915
- } else if (previousValue <= minValue) {
916
- direction = 1;
917
- } else {
918
- direction = Math.random() < 0.5 ? -1 : 1;
919
- }
920
-
921
- let newValue = previousValue + offset * direction;
922
- newValue = Math.max(minValue, Math.min(maxValue, newValue));
923
- return newValue;
924
- }
925
-
926
- function generateInitialData() {
927
- const data = [];
928
-
929
- let previousValue = minValue + Math.random() * (maxValue - minValue);
930
- data.push(previousValue);
931
-
932
- for (let i = 1; i < dataCount; i++) {
933
- const newValue = generateNextValue(previousValue);
934
- data.push(newValue);
935
- previousValue = newValue;
936
- }
937
-
938
- return data;
939
- }
940
-
941
- function AnimatedChart() {
942
- const [data, setData] = useState(generateInitialData);
943
-
944
- useEffect(() => {
945
- const intervalId = setInterval(() => {
946
- setData((currentData) => {
947
- const lastValue = currentData[currentData.length - 1] ?? minValue;
948
- const newValue = generateNextValue(lastValue);
949
-
950
- return [...currentData.slice(1), newValue];
951
- });
952
- }, updateInterval);
953
-
954
- return () => clearInterval(intervalId);
955
- }, []);
956
-
957
- const series = seriesConfig.map((config, index) => ({
958
- id: config.id,
959
- label: config.label,
960
- color: config.color,
961
- data: index === 0 ? data : Array(dataCount).fill(seriesSpacing),
962
- }));
993
+ function AnimatedChartExample() {
994
+ const animatedStates = [
995
+ { id: 'on', label: 'On' },
996
+ { id: 'off', label: 'Off' },
997
+ ];
998
+ const [animatedState, setAnimatedState] = useState(animatedStates[0]);
963
999
 
964
1000
  return (
965
- <BarChart
966
- animate={false}
967
- stacked
968
- height={{ base: 200, tablet: 250, desktop: 300 }}
969
- series={series}
970
- inset={0}
971
- showYAxis
972
- yAxis={{
973
- showGrid: true,
974
- width: 0,
975
- tickLabelFormatter: () => '',
976
- domain: { min: 0, max: domainLimit },
977
- }}
978
- />
1001
+ <VStack gap={2}>
1002
+ <HStack justifyContent="flex-end" gap={2} alignItems="center">
1003
+ <Text as="h3" font="headline">
1004
+ Animations
1005
+ </Text>
1006
+ <SegmentedTabs
1007
+ activeTab={animatedState}
1008
+ onChange={setAnimatedState}
1009
+ tabs={animatedStates}
1010
+ />
1011
+ </HStack>
1012
+ <AnimatedChart animate={animatedState.id === 'on'} />
1013
+ </VStack>
979
1014
  );
980
1015
  }
981
1016
 
982
- return <AnimatedChart />;
1017
+ return <AnimatedChartExample />;
983
1018
  }
984
1019
  ```
985
1020
 
@@ -1273,6 +1308,86 @@ function SunlightChartExample() {
1273
1308
  }
1274
1309
  ```
1275
1310
 
1311
+ #### Buy vs Sell
1312
+
1313
+ You can combine a horizontal BarChart with a custom legend to create a buy vs sell chart.
1314
+
1315
+ ```tsx live
1316
+ function BuyVsSellExample() {
1317
+ function BuyVsSellLegend({ buy, sell }: { buy: number; sell: number }) {
1318
+ return (
1319
+ <HStack gap={1} justifyContent="space-between">
1320
+ <DefaultLegendEntry
1321
+ label={
1322
+ <Text font="legal" color="fgMuted">
1323
+ {buy}% bought
1324
+ </Text>
1325
+ }
1326
+ color="var(--color-fgPositive)"
1327
+ />
1328
+ <DefaultLegendEntry
1329
+ label={
1330
+ <Text font="legal" color="fgMuted">
1331
+ {sell}% sold
1332
+ </Text>
1333
+ }
1334
+ color="var(--color-fgNegative)"
1335
+ />
1336
+ </HStack>
1337
+ );
1338
+ }
1339
+
1340
+ function BuyVsSellChart({
1341
+ buy,
1342
+ sell,
1343
+ animate = false,
1344
+ borderRadius = 3,
1345
+ height = 6,
1346
+ inset = 0,
1347
+ layout = 'horizontal',
1348
+ stackGap = 4,
1349
+ xAxis,
1350
+ yAxis,
1351
+ ...props
1352
+ }: Omit<BarChartProps, 'series'> & { buy: number; sell: number }) {
1353
+ return (
1354
+ <VStack gap={1.5}>
1355
+ <BarChart
1356
+ animate={animate}
1357
+ roundBaseline
1358
+ stacked
1359
+ borderRadius={borderRadius}
1360
+ height={height}
1361
+ inset={inset}
1362
+ layout={layout}
1363
+ series={[
1364
+ {
1365
+ id: 'buy',
1366
+ data: [buy],
1367
+ color: 'var(--color-fgPositive)',
1368
+ legendShape: 'circle',
1369
+ },
1370
+ {
1371
+ id: 'sell',
1372
+ data: [sell],
1373
+ color: 'var(--color-fgNegative)',
1374
+ legendShape: 'circle',
1375
+ },
1376
+ ]}
1377
+ stackGap={stackGap}
1378
+ xAxis={{ domainLimit: 'strict', ...xAxis }}
1379
+ yAxis={{ categoryPadding: 0, ...yAxis }}
1380
+ {...props}
1381
+ />
1382
+ <BuyVsSellLegend buy={buy} sell={sell} />
1383
+ </VStack>
1384
+ );
1385
+ }
1386
+
1387
+ return <BuyVsSellChart buy={76} sell={24} />;
1388
+ }
1389
+ ```
1390
+
1276
1391
  ## Props
1277
1392
 
1278
1393
  | Prop | Type | Required | Default | Description |
@@ -1288,15 +1403,11 @@ function SunlightChartExample() {
1288
1403
  | `background` | `currentColor \| fg \| fgMuted \| fgInverse \| fgPrimary \| fgWarning \| fgPositive \| fgNegative \| bg \| bgAlternate \| bgInverse \| bgOverlay \| bgElevation1 \| bgElevation2 \| bgPrimary \| bgPrimaryWash \| bgSecondary \| bgTertiary \| bgSecondaryWash \| bgNegative \| bgNegativeWash \| bgPositive \| bgPositiveWash \| bgWarning \| bgWarningWash \| bgLine \| bgLineHeavy \| bgLineInverse \| bgLinePrimary \| bgLinePrimarySubtle \| accentSubtleRed \| accentBoldRed \| accentSubtleGreen \| accentBoldGreen \| accentSubtleBlue \| accentBoldBlue \| accentSubtlePurple \| accentBoldPurple \| accentSubtleYellow \| accentBoldYellow \| accentSubtleGray \| accentBoldGray \| transparent` | No | `-` | - |
1289
1404
  | `barMinSize` | `number` | No | `-` | Minimum size for individual bars in the stack. |
1290
1405
  | `barPadding` | `number` | No | `0.1` | Padding between bar groups (0-1). |
1291
- | `borderBottomLeftRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000` | No | `-` | - |
1292
- | `borderBottomRightRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000` | No | `-` | - |
1293
1406
  | `borderBottomWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500` | No | `-` | - |
1294
1407
  | `borderColor` | `currentColor \| fg \| fgMuted \| fgInverse \| fgPrimary \| fgWarning \| fgPositive \| fgNegative \| bg \| bgAlternate \| bgInverse \| bgOverlay \| bgElevation1 \| bgElevation2 \| bgPrimary \| bgPrimaryWash \| bgSecondary \| bgTertiary \| bgSecondaryWash \| bgNegative \| bgNegativeWash \| bgPositive \| bgPositiveWash \| bgWarning \| bgWarningWash \| bgLine \| bgLineHeavy \| bgLineInverse \| bgLinePrimary \| bgLinePrimarySubtle \| accentSubtleRed \| accentBoldRed \| accentSubtleGreen \| accentBoldGreen \| accentSubtleBlue \| accentBoldBlue \| accentSubtlePurple \| accentBoldPurple \| accentSubtleYellow \| accentBoldYellow \| accentSubtleGray \| accentBoldGray \| transparent` | No | `-` | - |
1295
1408
  | `borderEndWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500` | No | `-` | - |
1296
- | `borderRadius` | `((BorderRadius \| { base?: BorderRadius; phone?: BorderRadius \| undefined; tablet?: BorderRadius \| undefined; desktop?: BorderRadius \| undefined; }) & number) \| undefined` | No | `4` | Border radius for the bar. |
1409
+ | `borderRadius` | `number` | No | `4` | Border radius for the bar. |
1297
1410
  | `borderStartWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500` | No | `-` | - |
1298
- | `borderTopLeftRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000` | No | `-` | - |
1299
- | `borderTopRightRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000` | No | `-` | - |
1300
1411
  | `borderTopWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500` | No | `-` | - |
1301
1412
  | `borderWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500` | No | `-` | - |
1302
1413
  | `bordered` | `boolean` | No | `-` | Add a border around all sides of the box. |
@@ -1344,6 +1455,7 @@ function SunlightChartExample() {
1344
1455
  | `inset` | `number \| Partial<ChartInset>` | No | `-` | Inset around the entire chart (outside the axes). |
1345
1456
  | `justifyContent` | `ResponsiveProp<left \| right \| center \| normal \| start \| end \| flex-start \| flex-end \| space-between \| space-around \| space-evenly \| stretch>` | No | `-` | - |
1346
1457
  | `key` | `Key \| null` | No | `-` | - |
1458
+ | `layout` | `horizontal \| vertical` | No | `'vertical'` | Chart layout - describes the direction bars/areas grow. - vertical (default): Bars grow vertically. X is category axis, Y is value axis. - horizontal: Bars grow horizontally. Y is category axis, X is value axis. |
1347
1459
  | `left` | `ResponsiveProp<Left<string \| number>>` | No | `-` | - |
1348
1460
  | `legend` | `null \| string \| number \| false \| true \| ReactElement<any, string \| JSXElementConstructor<any>> \| Iterable<ReactNode> \| ReactPortal` | No | `-` | Whether to show the legend or a custom legend element. - true renders the default Legend component - A React element renders that element as the legend - false or omitted hides the legend |
1349
1461
  | `legendAccessibilityLabel` | `string` | No | `'Legend'` | Accessibility label for the legend group. |
@@ -1398,8 +1510,8 @@ function SunlightChartExample() {
1398
1510
  | `userSelect` | `ResponsiveProp<text \| none \| all \| auto>` | No | `-` | - |
1399
1511
  | `visibility` | `ResponsiveProp<hidden \| visible>` | No | `-` | - |
1400
1512
  | `width` | `ResponsiveProp<Width<string \| number>>` | No | `-` | - |
1401
- | `xAxis` | `(Partial<AxisConfigProps> & SharedProps & { bandGridLinePlacement?: AxisBandPlacement; bandTickMarkPlacement?: AxisBandPlacement \| undefined; label?: string \| undefined; labelGap?: number \| undefined; minTickLabelGap?: number \| undefined; requestedTickCount?: number \| undefined; showGrid?: boolean \| undefined; showLine?: boolean \| undefined; showTickMarks?: boolean \| undefined; tickMarkSize?: number \| undefined; ticks?: number[] \| ((value: number) => boolean) \| undefined; tickMarkLabelGap?: number \| undefined; tickInterval?: number \| undefined; tickMinStep?: number \| undefined; tickMaxStep?: number \| undefined; } & { className?: string \| undefined; classNames?: { root?: string \| undefined; label?: string \| undefined; tickLabel?: string \| undefined; gridLine?: string \| undefined; line?: string \| undefined; tickMark?: string \| undefined; } \| undefined; style?: CSSProperties \| undefined; styles?: { root?: CSSProperties \| undefined; label?: CSSProperties \| undefined; tickLabel?: CSSProperties \| undefined; gridLine?: CSSProperties \| undefined; line?: CSSProperties \| undefined; tickMark?: CSSProperties \| undefined; } \| undefined; GridLineComponent?: LineComponent \| undefined; LineComponent?: LineComponent \| undefined; TickMarkLineComponent?: LineComponent \| undefined; tickLabelFormatter?: ((value: number) => ChartTextChildren) \| undefined; TickLabelComponent?: AxisTickLabelComponent \| undefined; } & { position?: top \| bottom \| undefined; height?: number \| undefined; }) \| undefined` | No | `-` | Configuration for x-axis. Accepts axis config and axis props. To show the axis, set showXAxis to true. |
1402
- | `yAxis` | `(Partial<AxisConfigProps> & SharedProps & { bandGridLinePlacement?: AxisBandPlacement; bandTickMarkPlacement?: AxisBandPlacement \| undefined; label?: string \| undefined; labelGap?: number \| undefined; minTickLabelGap?: number \| undefined; requestedTickCount?: number \| undefined; showGrid?: boolean \| undefined; showLine?: boolean \| undefined; showTickMarks?: boolean \| undefined; tickMarkSize?: number \| undefined; ticks?: number[] \| ((value: number) => boolean) \| undefined; tickMarkLabelGap?: number \| undefined; tickInterval?: number \| undefined; tickMinStep?: number \| undefined; tickMaxStep?: number \| undefined; } & { className?: string \| undefined; classNames?: { root?: string \| undefined; label?: string \| undefined; tickLabel?: string \| undefined; gridLine?: string \| undefined; line?: string \| undefined; tickMark?: string \| undefined; } \| undefined; style?: CSSProperties \| undefined; styles?: { root?: CSSProperties \| undefined; label?: CSSProperties \| undefined; tickLabel?: CSSProperties \| undefined; gridLine?: CSSProperties \| undefined; line?: CSSProperties \| undefined; tickMark?: CSSProperties \| undefined; } \| undefined; GridLineComponent?: LineComponent \| undefined; LineComponent?: LineComponent \| undefined; TickMarkLineComponent?: LineComponent \| undefined; tickLabelFormatter?: ((value: number) => ChartTextChildren) \| undefined; TickLabelComponent?: AxisTickLabelComponent \| undefined; } & { axisId?: string \| undefined; position?: left \| right \| undefined; width?: number \| undefined; }) \| undefined` | No | `-` | Configuration for y-axis. Accepts axis config and axis props. To show the axis, set showYAxis to true. |
1513
+ | `xAxis` | `(Partial<CartesianAxisConfigProps> & SharedProps & { bandGridLinePlacement?: AxisBandPlacement; bandTickMarkPlacement?: AxisBandPlacement \| undefined; label?: string \| undefined; labelGap?: number \| undefined; minTickLabelGap?: number \| undefined; requestedTickCount?: number \| undefined; showGrid?: boolean \| undefined; showLine?: boolean \| undefined; showTickMarks?: boolean \| undefined; tickMarkSize?: number \| undefined; ticks?: number[] \| ((value: number) => boolean) \| undefined; tickMarkLabelGap?: number \| undefined; tickInterval?: number \| undefined; tickMinStep?: number \| undefined; tickMaxStep?: number \| undefined; } & { className?: string \| undefined; classNames?: { root?: string \| undefined; label?: string \| undefined; tickLabel?: string \| undefined; gridLine?: string \| undefined; line?: string \| undefined; tickMark?: string \| undefined; } \| undefined; style?: CSSProperties \| undefined; styles?: { root?: CSSProperties \| undefined; label?: CSSProperties \| undefined; tickLabel?: CSSProperties \| undefined; gridLine?: CSSProperties \| undefined; line?: CSSProperties \| undefined; tickMark?: CSSProperties \| undefined; } \| undefined; GridLineComponent?: LineComponent \| undefined; LineComponent?: LineComponent \| undefined; TickMarkLineComponent?: LineComponent \| undefined; tickLabelFormatter?: ((value: number) => ChartTextChildren) \| undefined; TickLabelComponent?: AxisTickLabelComponent \| undefined; } & { axisId?: string \| undefined; position?: top \| bottom \| undefined; height?: number \| undefined; }) \| undefined` | No | `-` | Configuration for x-axis. Accepts axis config and axis props. To show the axis, set showXAxis to true. |
1514
+ | `yAxis` | `(Partial<CartesianAxisConfigProps> & SharedProps & { bandGridLinePlacement?: AxisBandPlacement; bandTickMarkPlacement?: AxisBandPlacement \| undefined; label?: string \| undefined; labelGap?: number \| undefined; minTickLabelGap?: number \| undefined; requestedTickCount?: number \| undefined; showGrid?: boolean \| undefined; showLine?: boolean \| undefined; showTickMarks?: boolean \| undefined; tickMarkSize?: number \| undefined; ticks?: number[] \| ((value: number) => boolean) \| undefined; tickMarkLabelGap?: number \| undefined; tickInterval?: number \| undefined; tickMinStep?: number \| undefined; tickMaxStep?: number \| undefined; } & { className?: string \| undefined; classNames?: { root?: string \| undefined; label?: string \| undefined; tickLabel?: string \| undefined; gridLine?: string \| undefined; line?: string \| undefined; tickMark?: string \| undefined; } \| undefined; style?: CSSProperties \| undefined; styles?: { root?: CSSProperties \| undefined; label?: CSSProperties \| undefined; tickLabel?: CSSProperties \| undefined; gridLine?: CSSProperties \| undefined; line?: CSSProperties \| undefined; tickMark?: CSSProperties \| undefined; } \| undefined; GridLineComponent?: LineComponent \| undefined; LineComponent?: LineComponent \| undefined; TickMarkLineComponent?: LineComponent \| undefined; tickLabelFormatter?: ((value: number) => ChartTextChildren) \| undefined; TickLabelComponent?: AxisTickLabelComponent \| undefined; } & { axisId?: string \| undefined; position?: left \| right \| undefined; width?: number \| undefined; }) \| undefined` | No | `-` | Configuration for y-axis. Accepts axis config and axis props. To show the axis, set showYAxis to true. |
1403
1515
  | `zIndex` | `inherit \| auto \| revert \| -moz-initial \| initial \| revert-layer \| unset` | No | `-` | - |
1404
1516
 
1405
1517
 
@@ -232,7 +232,9 @@ You can provide a `stackId` to stack series together.
232
232
 
233
233
  ### Axes
234
234
 
235
- You can configure your x and y axes with the `xAxis` and `yAxis` props. `xAxis` accepts an object while `yAxis` accepts an object or array.
235
+ You can configure your x and y axes with the `xAxis` and `yAxis` props. `xAxis` accepts an object or array, while `yAxis` accepts an object or array.
236
+
237
+ When `layout="horizontal"`, you can define multiple x-axes (for multiple value scales) but only one y-axis.
236
238
 
237
239
  ```jsx live
238
240
  <CartesianChart
@@ -1035,6 +1037,7 @@ function TradingTrends() {
1035
1037
  | `inset` | `number \| Partial<ChartInset>` | No | `-` | Inset around the entire chart (outside the axes). |
1036
1038
  | `justifyContent` | `ResponsiveProp<left \| right \| center \| normal \| start \| end \| flex-start \| flex-end \| space-between \| space-around \| space-evenly \| stretch>` | No | `-` | - |
1037
1039
  | `key` | `Key \| null` | No | `-` | - |
1040
+ | `layout` | `horizontal \| vertical` | No | `'vertical'` | Chart layout - describes the direction bars/areas grow. - vertical (default): Bars grow vertically. X is category axis, Y is value axis. - horizontal: Bars grow horizontally. Y is category axis, X is value axis. |
1038
1041
  | `left` | `ResponsiveProp<Left<string \| number>>` | No | `-` | - |
1039
1042
  | `legend` | `null \| string \| number \| false \| true \| ReactElement<any, string \| JSXElementConstructor<any>> \| Iterable<ReactNode> \| ReactPortal` | No | `-` | Whether to show the legend or a custom legend element. - true renders the default Legend component - A React element renders that element as the legend - false or omitted hides the legend |
1040
1043
  | `legendAccessibilityLabel` | `string` | No | `'Legend'` | Accessibility label for the legend group. |
@@ -1079,8 +1082,8 @@ function TradingTrends() {
1079
1082
  | `userSelect` | `ResponsiveProp<text \| none \| all \| auto>` | No | `-` | - |
1080
1083
  | `visibility` | `ResponsiveProp<hidden \| visible>` | No | `-` | - |
1081
1084
  | `width` | `ResponsiveProp<Width<string \| number>>` | No | `-` | - |
1082
- | `xAxis` | `Partial<Omit<AxisConfigProps, id>>` | No | `-` | Configuration for x-axis. |
1083
- | `yAxis` | `Partial<Omit<AxisConfigProps, data>> \| Partial<Omit<AxisConfigProps, data>>[]` | No | `-` | Configuration for y-axis(es). Can be a single config or array of configs. |
1085
+ | `xAxis` | `Partial<CartesianAxisConfigProps> \| Partial<CartesianAxisConfigProps>[]` | No | `-` | Configuration for x-axis(es). Can be a single config or array of configs. |
1086
+ | `yAxis` | `Partial<Omit<CartesianAxisConfigProps, data>> \| Partial<Omit<CartesianAxisConfigProps, data>>[]` | No | `-` | Configuration for y-axis(es). Can be a single config or array of configs. |
1084
1087
  | `zIndex` | `inherit \| auto \| revert \| -moz-initial \| initial \| revert-layer \| unset` | No | `-` | - |
1085
1088
 
1086
1089