@coinbase/cds-mcp-server 8.52.2 → 8.53.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.
Files changed (36) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/mcp-docs/mobile/components/Alert.txt +1 -1
  3. package/mcp-docs/mobile/components/AreaChart.txt +2 -0
  4. package/mcp-docs/mobile/components/BarChart.txt +33 -0
  5. package/mcp-docs/mobile/components/CartesianChart.txt +2 -0
  6. package/mcp-docs/mobile/components/Combobox.txt +380 -83
  7. package/mcp-docs/mobile/components/HeroSquare.txt +1 -1
  8. package/mcp-docs/mobile/components/InputChip.txt +75 -9
  9. package/mcp-docs/mobile/components/LineChart.txt +232 -112
  10. package/mcp-docs/mobile/components/MediaChip.txt +49 -26
  11. package/mcp-docs/mobile/components/NudgeCard.txt +1 -1
  12. package/mcp-docs/mobile/components/Pictogram.txt +1 -1
  13. package/mcp-docs/mobile/components/Scrubber.txt +2 -0
  14. package/mcp-docs/mobile/components/SelectChipAlpha.txt +52 -40
  15. package/mcp-docs/mobile/components/SpotIcon.txt +1 -1
  16. package/mcp-docs/mobile/components/SpotRectangle.txt +1 -1
  17. package/mcp-docs/mobile/components/SpotSquare.txt +1 -1
  18. package/mcp-docs/mobile/routes.txt +1 -1
  19. package/mcp-docs/web/components/Alert.txt +1 -1
  20. package/mcp-docs/web/components/Combobox.txt +422 -83
  21. package/mcp-docs/web/components/FullscreenAlert.txt +1 -1
  22. package/mcp-docs/web/components/HeroSquare.txt +1 -1
  23. package/mcp-docs/web/components/InputChip.txt +75 -9
  24. package/mcp-docs/web/components/Legend.txt +6 -6
  25. package/mcp-docs/web/components/LineChart.txt +16 -16
  26. package/mcp-docs/web/components/MediaChip.txt +49 -26
  27. package/mcp-docs/web/components/NudgeCard.txt +1 -1
  28. package/mcp-docs/web/components/Pictogram.txt +1 -1
  29. package/mcp-docs/web/components/SegmentedControl.txt +174 -0
  30. package/mcp-docs/web/components/SelectChipAlpha.txt +47 -13
  31. package/mcp-docs/web/components/SpotIcon.txt +1 -1
  32. package/mcp-docs/web/components/SpotRectangle.txt +1 -1
  33. package/mcp-docs/web/components/SpotSquare.txt +1 -1
  34. package/mcp-docs/web/components/TileButton.txt +1 -1
  35. package/mcp-docs/web/routes.txt +2 -1
  36. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  # InputChip
2
2
 
3
- A Chip used for removable selections.
3
+ A Chip used for removing selected values.
4
4
 
5
5
  ## Import
6
6
 
@@ -10,12 +10,38 @@ import { InputChip } from '@coinbase/cds-mobile/chips/InputChip'
10
10
 
11
11
  ## Examples
12
12
 
13
- ### Basic usage
13
+ InputChip is built for remove actions. For other uses, see [Chip](/components/inputs/Chip/) which supports interaction.
14
+
15
+ ### Basics
16
+
17
+ Use `onPress` for remove behavior.
18
+
19
+ ```tsx
20
+ function Example() {
21
+ const [selectedValues, setSelectedValues] = React.useState(['BTC', 'ETH', 'SOL']);
22
+
23
+ return (
24
+ <HStack gap={2} flexWrap="wrap">
25
+ {selectedValues.map((value) => (
26
+ <InputChip
27
+ key={value}
28
+ onPress={() => setSelectedValues((current) => current.filter((item) => item !== value))}
29
+ value={value}
30
+ />
31
+ ))}
32
+ </HStack>
33
+ );
34
+ }
35
+ ```
36
+
37
+ #### Disabled
38
+
39
+ Use `disabled` when the value should stay visible but not removable.
14
40
 
15
41
  ```tsx
16
42
  function Example() {
17
43
  return (
18
- <HStack gap={2}>
44
+ <HStack gap={2} flexWrap="wrap">
19
45
  <InputChip onPress={() => console.log('Remove Basic')} value="Basic Chip" />
20
46
  <InputChip disabled onPress={() => {}} value="Disabled Chip" />
21
47
  </HStack>
@@ -23,20 +49,22 @@ function Example() {
23
49
  }
24
50
  ```
25
51
 
26
- ### With Custom Start Element
52
+ ### Styling
53
+
54
+ #### With start content
27
55
 
28
56
  ```tsx
29
57
  function Example() {
30
58
  return (
31
59
  <VStack gap={2}>
32
- <HStack gap={2}>
60
+ <HStack gap={2} flexWrap="wrap">
33
61
  <InputChip
34
62
  onPress={() => console.log('Remove Star')}
35
63
  value="With Icon"
36
64
  start={<Icon name="star" />}
37
65
  />
38
66
  </HStack>
39
- <HStack gap={2}>
67
+ <HStack gap={2} flexWrap="wrap">
40
68
  <InputChip
41
69
  onPress={() => console.log('Remove BTC')}
42
70
  value="BTC"
@@ -53,16 +81,54 @@ function Example() {
53
81
  }
54
82
  ```
55
83
 
56
- ### With Custom Accessibility Label
84
+ #### Compact
85
+
86
+ Use `compact` to reduce chip height and spacing in dense layouts.
87
+
88
+ ```tsx
89
+ function Example() {
90
+ return (
91
+ <HStack gap={2} flexWrap="wrap">
92
+ <InputChip onPress={() => console.log('Remove Default')} value="Default" />
93
+ <InputChip compact onPress={() => console.log('Remove Compact')} value="Compact" />
94
+ </HStack>
95
+ );
96
+ }
97
+ ```
98
+
99
+ #### Invert color scheme
100
+
101
+ Use `invertColorScheme` to emphasize removable values.
102
+
103
+ ```tsx
104
+ function Example() {
105
+ return (
106
+ <HStack gap={2} flexWrap="wrap">
107
+ <InputChip onPress={() => console.log('Remove Default')} value="Default" />
108
+ <InputChip
109
+ invertColorScheme
110
+ onPress={() => console.log('Remove Inverted')}
111
+ value="Inverted"
112
+ />
113
+ </HStack>
114
+ );
115
+ }
116
+ ```
117
+
118
+ ### Accessibility
119
+
120
+ InputChip defaults to a remove label (`Remove ${children}` for string content, otherwise `Remove option`).
121
+ Override `accessibilityLabel` when you need more specific wording.
57
122
 
58
123
  ```tsx
59
124
  function Example() {
60
125
  return (
61
- <HStack gap={2}>
126
+ <HStack gap={2} flexWrap="wrap">
127
+ <InputChip onPress={() => console.log('Remove BTC')} value="BTC" />
62
128
  <InputChip
63
129
  onPress={() => console.log('Remove Custom')}
64
130
  value="Custom Label"
65
- accessibilityLabel="Custom remove action"
131
+ accessibilityLabel="Remove custom selection"
66
132
  />
67
133
  </HStack>
68
134
  );
@@ -75,66 +75,86 @@ function HorizontalLine() {
75
75
  LineChart also supports multiple lines, interaction, and axes.
76
76
  Other props, such as `areaType` can be applied to the chart as a whole or per series.
77
77
 
78
- ```jsx
79
- <LineChart
80
- enableScrubbing
81
- showArea
82
- series={[
83
- {
84
- id: 'pageViews',
85
- data: [2400, 1398, 9800, 3908, 4800, 3800, 4300],
86
- color: theme.color.accentBoldGreen,
87
- // Label will render next to scrubber beacon
88
- label: 'Page Views',
89
- },
90
- {
91
- id: 'uniqueVisitors',
92
- data: [4000, 3000, 2000, 2780, 1890, 2390, 3490],
93
- color: theme.color.accentBoldPurple,
94
- label: 'Unique Visitors',
95
- // Default area is gradient
96
- areaType: 'dotted',
97
- },
98
- ]}
99
- xAxis={{
100
- // Used on the x-axis to provide context for each index from the series data array
101
- data: ['Page A', 'Page B', 'Page C', 'Page D', 'Page E', 'Page F', 'Page G'],
102
- }}
103
- >
104
- <Scrubber />
105
- </LineChart>
78
+ ```tsx
79
+ function MultipleLine() {
80
+ const pages = useMemo(
81
+ () => ['Page A', 'Page B', 'Page C', 'Page D', 'Page E', 'Page F', 'Page G'],
82
+ [],
83
+ );
84
+ const pageViews = useMemo(() => [2400, 1398, 9800, 3908, 4800, 3800, 4300], []);
85
+ const uniqueVisitors = useMemo(() => [4000, 3000, 2000, 2780, 1890, 2390, 3490], []);
86
+
87
+ const chartAccessibilityLabel = `Website visitors across ${pageViews.length} pages.`;
88
+ const getScrubberAccessibilityLabel = useCallback(
89
+ (index: number) =>
90
+ `${pages[index]} has ${pageViews[index]} views and ${uniqueVisitors[index]} unique visitors.`,
91
+ [pages, pageViews, uniqueVisitors],
92
+ );
93
+
94
+ return (
95
+ <LineChart
96
+ enableScrubbing
97
+ showArea
98
+ accessibilityLabel={chartAccessibilityLabel}
99
+ getScrubberAccessibilityLabel={getScrubberAccessibilityLabel}
100
+ series={[
101
+ {
102
+ id: 'pageViews',
103
+ data: pageViews,
104
+ color: theme.color.accentBoldGreen,
105
+ label: 'Page Views',
106
+ },
107
+ {
108
+ id: 'uniqueVisitors',
109
+ data: uniqueVisitors,
110
+ color: theme.color.accentBoldPurple,
111
+ label: 'Unique Visitors',
112
+ areaType: 'dotted',
113
+ },
114
+ ]}
115
+ xAxis={{ data: pages }}
116
+ >
117
+ <Scrubber />
118
+ </LineChart>
119
+ );
120
+ }
106
121
  ```
107
122
 
108
123
  ### Data
109
124
 
110
125
  The data array for each series defines the y values for that series. You can adjust the y values for a series of data by setting the `data` prop on the xAxis.
111
126
 
112
- ```jsx
113
- const yData = [2, 5.5, 2, 8.5, 1.5, 5];
114
- const xData = [1, 2, 3, 5, 8, 10];
127
+ ```tsx
128
+ function DataFormat() {
129
+ const yData = useMemo(() => [2, 5.5, 2, 8.5, 1.5, 5], []);
130
+ const xData = useMemo(() => [1, 2, 3, 5, 8, 10], []);
131
+
132
+ const chartAccessibilityLabel = `Chart with custom X and Y data. ${yData.length} data points.`;
133
+ const getScrubberAccessibilityLabel = useCallback(
134
+ (index: number) => `Point ${index + 1}: X value ${xData[index]}, Y value ${yData[index]}`,
135
+ [xData, yData],
136
+ );
115
137
 
116
- return (
117
- <LineChart
118
- enableScrubbing
119
- showArea
120
- series={[
121
- {
122
- id: 'line',
123
- data: yData,
124
- },
125
- ]}
126
- xAxis={{ data: xData, showLine: true, showTickMarks: true, showGrid: true }}
127
- yAxis={{
128
- domain: { min: 0 },
129
- position: 'left',
130
- showLine: true,
131
- showTickMarks: true,
132
- showGrid: true,
133
- }}
134
- >
135
- <Scrubber />
136
- </LineChart>
137
- );
138
+ return (
139
+ <LineChart
140
+ enableScrubbing
141
+ showArea
142
+ accessibilityLabel={chartAccessibilityLabel}
143
+ getScrubberAccessibilityLabel={getScrubberAccessibilityLabel}
144
+ series={[{ id: 'line', data: yData }]}
145
+ xAxis={{ data: xData, showLine: true, showTickMarks: true, showGrid: true }}
146
+ yAxis={{
147
+ domain: { min: 0 },
148
+ position: 'left',
149
+ showLine: true,
150
+ showTickMarks: true,
151
+ showGrid: true,
152
+ }}
153
+ >
154
+ <Scrubber />
155
+ </LineChart>
156
+ );
157
+ }
138
158
  ```
139
159
 
140
160
  #### Live Updates
@@ -143,7 +163,7 @@ You can change the data passed in via `series` prop to update the chart.
143
163
 
144
164
  You can also use the `useRef` hook to reference the scrubber and pulse it on each update.
145
165
 
146
- ```jsx
166
+ ```tsx
147
167
  function LiveUpdates() {
148
168
  const scrubberRef = useRef < ScrubberRef > null;
149
169
 
@@ -198,10 +218,18 @@ function LiveUpdates() {
198
218
  return () => clearInterval(priceUpdateInterval);
199
219
  }, [intervalSeconds, maxPercentChange]);
200
220
 
221
+ const chartAccessibilityLabel = `Live price chart with ${priceData.length} data points.`;
222
+ const getScrubberAccessibilityLabel = useCallback(
223
+ (index: number) => `Point ${index + 1}: ${priceData[index]}`,
224
+ [priceData],
225
+ );
226
+
201
227
  return (
202
228
  <LineChart
203
229
  enableScrubbing
204
230
  showArea
231
+ accessibilityLabel={chartAccessibilityLabel}
232
+ getScrubberAccessibilityLabel={getScrubberAccessibilityLabel}
205
233
  height={200}
206
234
  inset={{ right: 64 }}
207
235
  series={[
@@ -226,9 +254,24 @@ Note that scrubber beacons and points are still only shown at non-null data valu
226
254
  ```tsx
227
255
  function MissingData() {
228
256
  const theme = useTheme();
229
- const pages = ['Page A', 'Page B', 'Page C', 'Page D', 'Page E', 'Page F', 'Page G'];
230
- const pageViews = [2400, 1398, null, 3908, 4800, 3800, 4300];
231
- const uniqueVisitors = [4000, 3000, null, 2780, 1890, 2390, 3490];
257
+ const pages = useMemo(
258
+ () => ['Page A', 'Page B', 'Page C', 'Page D', 'Page E', 'Page F', 'Page G'],
259
+ [],
260
+ );
261
+ const pageViews = useMemo(() => [2400, 1398, null, 3908, 4800, 3800, 4300], []);
262
+ const uniqueVisitors = useMemo(() => [4000, 3000, null, 2780, 1890, 2390, 3490], []);
263
+
264
+ const chartAccessibilityLabel = `Website visitors across ${pages.length} pages. Some data points are missing.`;
265
+ const getScrubberAccessibilityLabel = useCallback(
266
+ (index: number) => {
267
+ const pv = pageViews[index];
268
+ const uv = uniqueVisitors[index];
269
+ const pvStr = pv != null ? pv : 'no data';
270
+ const uvStr = uv != null ? uv : 'no data';
271
+ return `${pages[index]}: ${pvStr} views, ${uvStr} unique visitors.`;
272
+ },
273
+ [pages, pageViews, uniqueVisitors],
274
+ );
232
275
 
233
276
  const numberFormatter = useCallback(
234
277
  (value: number) => new Intl.NumberFormat('en-US', { maximumFractionDigits: 0 }).format(value),
@@ -241,6 +284,8 @@ function MissingData() {
241
284
  showArea
242
285
  showXAxis
243
286
  showYAxis
287
+ accessibilityLabel={chartAccessibilityLabel}
288
+ getScrubberAccessibilityLabel={getScrubberAccessibilityLabel}
244
289
  height={200}
245
290
  // You can render points at every valid data point by always returning true
246
291
  points
@@ -325,9 +370,16 @@ LineChart uses `linear` scaling on axes by default, but you can also use other t
325
370
 
326
371
  Charts have built in functionality enabled through scrubbing, which can be used by setting `enableScrubbing` to true. You can listen to value changes through `onScrubberPositionChange`. Adding `Scrubber` to LineChart showcases the current scrubber position.
327
372
 
328
- ```jsx
373
+ ```tsx
329
374
  function Interaction() {
330
375
  const [scrubberPosition, setScrubberPosition] = useState<number | undefined>();
376
+ const data = useMemo(() => [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58], []);
377
+
378
+ const chartAccessibilityLabel = `Price chart with ${data.length} data points. Swipe to navigate.`;
379
+ const getScrubberAccessibilityLabel = useCallback(
380
+ (index: number) => `Point ${index + 1}: ${data[index]}`,
381
+ [data],
382
+ );
331
383
 
332
384
  return (
333
385
  <VStack gap={2}>
@@ -339,14 +391,11 @@ function Interaction() {
339
391
  <LineChart
340
392
  enableScrubbing
341
393
  showArea
394
+ accessibilityLabel={chartAccessibilityLabel}
395
+ getScrubberAccessibilityLabel={getScrubberAccessibilityLabel}
342
396
  height={200}
343
397
  onScrubberPositionChange={setScrubberPosition}
344
- series={[
345
- {
346
- id: 'prices',
347
- data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58],
348
- },
349
- ]}
398
+ series={[{ id: 'prices', data }]}
350
399
  >
351
400
  <Scrubber />
352
401
  </LineChart>
@@ -538,11 +587,28 @@ const PerformanceChart = memo(
538
587
  [formatDate, sparklineTimePeriodDataTimestamps],
539
588
  );
540
589
 
590
+ const chartAccessibilityLabel = `Bitcoin price chart with high, actual, and low series. ${sparklineTimePeriodDataValues.length} data points. Swipe to navigate.`;
591
+ const getScrubberAccessibilityLabel = useCallback(
592
+ (index: number) => {
593
+ const price = formatPriceThousands(sparklineTimePeriodDataValues[index]);
594
+ const date = formatDate(sparklineTimePeriodDataTimestamps[index]);
595
+ return `Point ${index + 1}: ${price}, ${date}`;
596
+ },
597
+ [
598
+ formatDate,
599
+ formatPriceThousands,
600
+ sparklineTimePeriodDataTimestamps,
601
+ sparklineTimePeriodDataValues,
602
+ ],
603
+ );
604
+
541
605
  return (
542
606
  <LineChart
543
607
  enableScrubbing
544
608
  showArea
545
609
  showYAxis
610
+ accessibilityLabel={chartAccessibilityLabel}
611
+ getScrubberAccessibilityLabel={getScrubberAccessibilityLabel}
546
612
  areaType="dotted"
547
613
  height={300}
548
614
  inset={{ top: 52, left: 0, right: 0 }}
@@ -585,6 +651,8 @@ By default, charts will not track gestures that go outside of the chart bounds.
585
651
  <LineChart
586
652
  enableScrubbing
587
653
  allowOverflowGestures
654
+ accessibilityLabel="Chart with overflow gestures. Swipe to navigate."
655
+ getScrubberAccessibilityLabel={(index) => `Point ${index + 1}`}
588
656
  ...
589
657
  >
590
658
  ...
@@ -614,42 +682,38 @@ Also, you can toggle animations by setting `animate` to `true` or `false`.
614
682
 
615
683
  ### Accessibility
616
684
 
617
- You can use `accessibilityLabel` on the chart to provide a descriptive label.
685
+ Use `accessibilityLabel` on `LineChart` (or `CartesianChart`) to provide both:
686
+
687
+ - a summary label when focus first lands on the chart
688
+ - point-by-point labels while swiping through scrubber targets
689
+
690
+ `getScrubberAccessibilityLabel` defines the per-segment text announced by screen readers. You do not need to add a `Scrubber` component for accessibility—`enableScrubbing` with `getScrubberAccessibilityLabel` is sufficient. BarChart and other charts work the same way.
618
691
 
619
692
  ```tsx
620
693
  function BasicAccessible() {
621
- const [scrubberPosition, setScrubberPosition] = useState<number | undefined>();
622
694
  const data = useMemo(() => [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58], []);
623
695
 
624
- // Chart-level accessibility label provides overview
625
- const chartAccessibilityLabel = useMemo(() => {
626
- const currentPrice = data[data.length - 1];
627
- return `Price chart showing trend over ${data.length} data points. Current value: ${currentPrice}. Use arrow keys to adjust view`;
628
- }, [data]);
629
-
630
- // Scrubber-level accessibility label provides specific position info
631
- const scrubberAccessibilityLabel = useCallback(
632
- (index: number) => {
633
- return `Price at position ${index + 1} of ${data.length}: ${data[index]}`;
634
- },
696
+ // Chart-level accessibility label provides overview when focus lands on the chart
697
+ const chartAccessibilityLabel = useMemo(
698
+ () =>
699
+ `Price chart showing trend over ${data.length} data points. Current value: ${data[data.length - 1]}. Swipe to navigate.`,
635
700
  [data],
636
701
  );
637
702
 
638
- const accessibilityLabel = useMemo(() => {
639
- if (scrubberPosition !== undefined) {
640
- return scrubberAccessibilityLabel(scrubberPosition);
641
- }
642
- return chartAccessibilityLabel;
643
- }, [scrubberPosition, chartAccessibilityLabel, scrubberAccessibilityLabel]);
703
+ // Per-segment label announced when screen reader user taps or swipes to a segment
704
+ const getScrubberAccessibilityLabel = useCallback(
705
+ (index: number) => `Price at position ${index + 1} of ${data.length}: ${data[index]}`,
706
+ [data],
707
+ );
644
708
 
645
709
  return (
646
710
  <LineChart
647
711
  enableScrubbing
648
712
  showArea
649
713
  showYAxis
650
- accessibilityLabel={accessibilityLabel}
714
+ accessibilityLabel={chartAccessibilityLabel}
715
+ getScrubberAccessibilityLabel={getScrubberAccessibilityLabel}
651
716
  height={200}
652
- onScrubberPositionChange={setScrubberPosition}
653
717
  series={[
654
718
  {
655
719
  id: 'prices',
@@ -894,9 +958,17 @@ function GainLossChart() {
894
958
  />
895
959
  ));
896
960
 
961
+ const chartAccessibilityLabel = `Price chart with ${data.length} data points.`;
962
+ const getScrubberAccessibilityLabel = useCallback(
963
+ (index: number) => `Point ${index + 1}: ${data[index]}`,
964
+ [data],
965
+ );
966
+
897
967
  return (
898
968
  <CartesianChart
899
969
  enableScrubbing
970
+ accessibilityLabel={chartAccessibilityLabel}
971
+ getScrubberAccessibilityLabel={getScrubberAccessibilityLabel}
900
972
  height={200}
901
973
  series={[
902
974
  {
@@ -1005,30 +1077,35 @@ You can customize lines by placing props in `LineChart` or at each individual se
1005
1077
 
1006
1078
  You can also add instances of [ReferenceLine](/components/charts/ReferenceLine) to your LineChart to highlight a specific x or y value.
1007
1079
 
1008
- ```jsx
1009
- <LineChart
1010
- enableScrubbing
1011
- showArea
1012
- height={200}
1013
- series={[
1014
- {
1015
- id: 'prices',
1016
- data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58],
1017
- color: theme.color.fgPositive,
1018
- },
1019
- ]}
1020
- xAxis={{
1021
- // Give space before the end of the chart for the scrubber
1022
- range: ({ min, max }) => ({ min, max: max - 24 }),
1023
- }}
1024
- >
1025
- <ReferenceLine
1026
- LineComponent={(props) => <DottedLine {...props} dashIntervals={[0, 16]} strokeWidth={3} />}
1027
- dataY={10}
1028
- stroke={theme.color.fg}
1029
- />
1030
- <Scrubber />
1031
- </LineChart>
1080
+ ```tsx
1081
+ function ReferenceLineExample() {
1082
+ const data = useMemo(() => [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58], []);
1083
+
1084
+ const chartAccessibilityLabel = `Price chart with reference line at 10. ${data.length} data points.`;
1085
+ const getScrubberAccessibilityLabel = useCallback(
1086
+ (index: number) => `Point ${index + 1}: ${data[index]}`,
1087
+ [data],
1088
+ );
1089
+
1090
+ return (
1091
+ <LineChart
1092
+ enableScrubbing
1093
+ showArea
1094
+ accessibilityLabel={chartAccessibilityLabel}
1095
+ getScrubberAccessibilityLabel={getScrubberAccessibilityLabel}
1096
+ height={200}
1097
+ series={[{ id: 'prices', data, color: theme.color.fgPositive }]}
1098
+ xAxis={{ range: ({ min, max }) => ({ min, max: max - 24 }) }}
1099
+ >
1100
+ <ReferenceLine
1101
+ LineComponent={(props) => <DottedLine {...props} dashIntervals={[0, 16]} strokeWidth={3} />}
1102
+ dataY={10}
1103
+ stroke={theme.color.fg}
1104
+ />
1105
+ <Scrubber />
1106
+ </LineChart>
1107
+ );
1108
+ }
1032
1109
  ```
1033
1110
 
1034
1111
  #### Points
@@ -1090,9 +1167,19 @@ You can have scrubber beacon's pulse by either adding `idlePulse` to Scrubber or
1090
1167
  ```tsx
1091
1168
  function StylingScrubber() {
1092
1169
  const theme = useTheme();
1093
- const pages = ['Page A', 'Page B', 'Page C', 'Page D', 'Page E', 'Page F', 'Page G'];
1094
- const pageViews = [2400, 1398, 9800, 3908, 4800, 3800, 4300];
1095
- const uniqueVisitors = [4000, 3000, 2000, 2780, 1890, 2390, 3490];
1170
+ const pages = useMemo(
1171
+ () => ['Page A', 'Page B', 'Page C', 'Page D', 'Page E', 'Page F', 'Page G'],
1172
+ [],
1173
+ );
1174
+ const pageViews = useMemo(() => [2400, 1398, 9800, 3908, 4800, 3800, 4300], []);
1175
+ const uniqueVisitors = useMemo(() => [4000, 3000, 2000, 2780, 1890, 2390, 3490], []);
1176
+
1177
+ const chartAccessibilityLabel = `Website visitors across ${pageViews.length} pages.`;
1178
+ const getScrubberAccessibilityLabel = useCallback(
1179
+ (index: number) =>
1180
+ `${pages[index]}: ${pageViews[index]} views, ${uniqueVisitors[index]} unique visitors.`,
1181
+ [pages, pageViews, uniqueVisitors],
1182
+ );
1096
1183
 
1097
1184
  const numberFormatter = useCallback(
1098
1185
  (value: number) => new Intl.NumberFormat('en-US', { maximumFractionDigits: 0 }).format(value),
@@ -1105,6 +1192,8 @@ function StylingScrubber() {
1105
1192
  showArea
1106
1193
  showXAxis
1107
1194
  showYAxis
1195
+ accessibilityLabel={chartAccessibilityLabel}
1196
+ getScrubberAccessibilityLabel={getScrubberAccessibilityLabel}
1108
1197
  height={200}
1109
1198
  series={[
1110
1199
  {
@@ -1364,6 +1453,21 @@ function AssetPriceWithDottedArea() {
1364
1453
  return `${dayOfWeek}, ${monthDay}, ${time}`;
1365
1454
  }, []);
1366
1455
 
1456
+ const chartAccessibilityLabel = useMemo(
1457
+ () =>
1458
+ `Bitcoin price chart for ${timePeriod.label} period. Current price: ${formatPrice(currentPrice)}. Swipe to navigate.`,
1459
+ [currentPrice, formatPrice, timePeriod.label],
1460
+ );
1461
+
1462
+ const getScrubberAccessibilityLabel = useCallback(
1463
+ (index: number) => {
1464
+ const price = formatPrice(sparklineTimePeriodDataValues[index]);
1465
+ const date = formatDate(sparklineTimePeriodDataTimestamps[index]);
1466
+ return `${price} ${date}`;
1467
+ },
1468
+ [formatDate, formatPrice, sparklineTimePeriodDataTimestamps, sparklineTimePeriodDataValues],
1469
+ );
1470
+
1367
1471
  return (
1368
1472
  <VStack gap={2}>
1369
1473
  <SectionHeader
@@ -1378,6 +1482,8 @@ function AssetPriceWithDottedArea() {
1378
1482
  <LineChart
1379
1483
  enableScrubbing
1380
1484
  showArea
1485
+ accessibilityLabel={chartAccessibilityLabel}
1486
+ getScrubberAccessibilityLabel={getScrubberAccessibilityLabel}
1381
1487
  areaType="dotted"
1382
1488
  height={200}
1383
1489
  inset={{ top: 52 }}
@@ -1573,10 +1679,22 @@ function MonotoneAssetPrice() {
1573
1679
  [theme.color.fg, theme.color.bg],
1574
1680
  );
1575
1681
 
1682
+ const chartAccessibilityLabel = `Price chart with ${prices.length} data points. Swipe to navigate.`;
1683
+ const getScrubberAccessibilityLabel = useCallback(
1684
+ (index: number) => {
1685
+ const price = scrubberPriceFormatter.format(prices[index].value);
1686
+ const date = formatDate(prices[index].date);
1687
+ return `${price} USD ${date}`;
1688
+ },
1689
+ [formatDate, prices, scrubberPriceFormatter],
1690
+ );
1691
+
1576
1692
  return (
1577
1693
  <LineChart
1578
1694
  enableScrubbing
1579
1695
  showYAxis
1696
+ accessibilityLabel={chartAccessibilityLabel}
1697
+ getScrubberAccessibilityLabel={getScrubberAccessibilityLabel}
1580
1698
  height={200}
1581
1699
  inset={{ top: 64 }}
1582
1700
  series={[
@@ -1878,6 +1996,7 @@ function ForecastAssetPrice() {
1878
1996
  | `fontSize` | `FontSize \| inherit` | No | `-` | - |
1879
1997
  | `fontWeight` | `inherit \| FontWeight` | No | `-` | - |
1880
1998
  | `gap` | `0 \| 1 \| 2 \| 0.25 \| 0.5 \| 0.75 \| 1.5 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10` | No | `-` | - |
1999
+ | `getScrubberAccessibilityLabel` | `((dataIndex: number) => string)` | No | `-` | Function that returns the accessibility label for each scrubber point. Receives dataIndex for each scrubber point label. |
1881
2000
  | `height` | `string \| number` | No | `-` | - |
1882
2001
  | `inset` | `number \| Partial<ChartInset>` | No | `-` | Inset around the entire chart (outside the axes). |
1883
2002
  | `justifyContent` | `flex-start \| flex-end \| center \| space-between \| space-around \| space-evenly` | No | `-` | - |
@@ -1927,6 +2046,7 @@ function ForecastAssetPrice() {
1927
2046
  | `ref` | `((instance: View \| null) => void) \| RefObject<View> \| null` | No | `-` | - |
1928
2047
  | `right` | `string \| number` | No | `-` | - |
1929
2048
  | `rowGap` | `0 \| 1 \| 2 \| 0.25 \| 0.5 \| 0.75 \| 1.5 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10` | No | `-` | - |
2049
+ | `scrubberAccessibilityLabelStep` | `number` | No | `Computed from data length (targeting 10 samples)` | Number of data points to move between screen-reader samples. |
1930
2050
  | `series` | `LineSeries[]` | No | `-` | Configuration objects that define how to visualize the data. Each series supports Line component props for individual customization. |
1931
2051
  | `showArea` | `boolean` | No | `-` | Whether to show area fill under the line. |
1932
2052
  | `showXAxis` | `boolean` | No | `-` | Whether to show the X axis. |