@coinbase/cds-mcp-server 8.28.1 → 8.29.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 (82) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/mcp-docs/mobile/components/Accordion.txt +3 -1
  3. package/mcp-docs/mobile/components/Alert.txt +3 -1
  4. package/mcp-docs/mobile/components/Banner.txt +14 -14
  5. package/mcp-docs/mobile/components/Button.txt +173 -30
  6. package/mcp-docs/mobile/components/Carousel.txt +24 -24
  7. package/mcp-docs/mobile/components/Combobox.txt +187 -0
  8. package/mcp-docs/mobile/components/ContainedAssetCard.txt +4 -4
  9. package/mcp-docs/mobile/components/ContentCard.txt +29 -27
  10. package/mcp-docs/mobile/components/ContentCardBody.txt +4 -4
  11. package/mcp-docs/mobile/components/ContentCardHeader.txt +2 -2
  12. package/mcp-docs/mobile/components/FloatingAssetCard.txt +6 -6
  13. package/mcp-docs/mobile/components/IconButton.txt +126 -51
  14. package/mcp-docs/mobile/components/LineChart.txt +3 -2
  15. package/mcp-docs/mobile/components/MultiContentModule.txt +6 -6
  16. package/mcp-docs/mobile/components/Numpad.txt +2 -2
  17. package/mcp-docs/mobile/components/PageHeader.txt +3 -1
  18. package/mcp-docs/mobile/components/PeriodSelector.txt +4 -4
  19. package/mcp-docs/mobile/components/Pressable.txt +6 -2
  20. package/mcp-docs/mobile/components/ProgressBarWithFixedLabels.txt +4 -4
  21. package/mcp-docs/mobile/components/ProgressBarWithFloatLabel.txt +2 -2
  22. package/mcp-docs/mobile/components/ProgressCircle.txt +5 -1
  23. package/mcp-docs/mobile/components/SelectChip.txt +2 -0
  24. package/mcp-docs/mobile/components/SelectChipAlpha.txt +1 -1
  25. package/mcp-docs/mobile/components/SlideButton.txt +2 -2
  26. package/mcp-docs/mobile/components/Sparkline.txt +3 -1
  27. package/mcp-docs/mobile/components/SparklineGradient.txt +3 -1
  28. package/mcp-docs/mobile/components/SparklineInteractiveHeader.txt +3 -1
  29. package/mcp-docs/mobile/components/TabbedChips.txt +3 -1
  30. package/mcp-docs/mobile/components/Tag.txt +19 -9
  31. package/mcp-docs/mobile/components/TextInput.txt +9 -3
  32. package/mcp-docs/mobile/components/Tray.txt +2 -0
  33. package/mcp-docs/mobile/components/UpsellCard.txt +16 -16
  34. package/mcp-docs/mobile/hooks/useDimensions.txt +4 -4
  35. package/mcp-docs/mobile/hooks/useMergeRefs.txt +4 -4
  36. package/mcp-docs/mobile/hooks/usePreviousValue.txt +5 -5
  37. package/mcp-docs/mobile/hooks/useRefMap.txt +6 -6
  38. package/mcp-docs/mobile/routes.txt +1 -0
  39. package/mcp-docs/web/components/Accordion.txt +3 -1
  40. package/mcp-docs/web/components/Alert.txt +3 -1
  41. package/mcp-docs/web/components/Banner.txt +14 -14
  42. package/mcp-docs/web/components/Button.txt +188 -34
  43. package/mcp-docs/web/components/Carousel.txt +71 -65
  44. package/mcp-docs/web/components/Combobox.txt +176 -0
  45. package/mcp-docs/web/components/ContainedAssetCard.txt +4 -4
  46. package/mcp-docs/web/components/ContentCard.txt +29 -27
  47. package/mcp-docs/web/components/ContentCardBody.txt +4 -4
  48. package/mcp-docs/web/components/ContentCardHeader.txt +2 -2
  49. package/mcp-docs/web/components/FloatingAssetCard.txt +6 -6
  50. package/mcp-docs/web/components/FullscreenModal.txt +12 -4
  51. package/mcp-docs/web/components/GridColumn.txt +12 -4
  52. package/mcp-docs/web/components/IconButton.txt +164 -189
  53. package/mcp-docs/web/components/LineChart.txt +3 -2
  54. package/mcp-docs/web/components/MultiContentModule.txt +6 -6
  55. package/mcp-docs/web/components/PageHeader.txt +11 -9
  56. package/mcp-docs/web/components/ProgressBarWithFixedLabels.txt +4 -4
  57. package/mcp-docs/web/components/ProgressBarWithFloatLabel.txt +2 -2
  58. package/mcp-docs/web/components/ProgressCircle.txt +5 -1
  59. package/mcp-docs/web/components/SelectChipAlpha.txt +1 -1
  60. package/mcp-docs/web/components/Sidebar.txt +2 -2
  61. package/mcp-docs/web/components/Sparkline.txt +3 -1
  62. package/mcp-docs/web/components/SparklineGradient.txt +3 -1
  63. package/mcp-docs/web/components/SparklineInteractiveHeader.txt +3 -1
  64. package/mcp-docs/web/components/TabbedChips.txt +3 -1
  65. package/mcp-docs/web/components/TableBody.txt +2 -2
  66. package/mcp-docs/web/components/TableCaption.txt +2 -2
  67. package/mcp-docs/web/components/TableCell.txt +6 -6
  68. package/mcp-docs/web/components/Tag.txt +19 -9
  69. package/mcp-docs/web/components/TextInput.txt +9 -3
  70. package/mcp-docs/web/components/Tray.txt +2 -1
  71. package/mcp-docs/web/components/UpsellCard.txt +16 -16
  72. package/mcp-docs/web/hooks/useDimensions.txt +4 -4
  73. package/mcp-docs/web/hooks/useHasMounted.txt +7 -3
  74. package/mcp-docs/web/hooks/useIsoEffect.txt +1 -1
  75. package/mcp-docs/web/hooks/useMergeRefs.txt +4 -4
  76. package/mcp-docs/web/hooks/useOverlayContentContext.txt +8 -8
  77. package/mcp-docs/web/hooks/usePreviousValue.txt +5 -5
  78. package/mcp-docs/web/hooks/useRefMap.txt +6 -6
  79. package/mcp-docs/web/hooks/useScrollBlocker.txt +1 -1
  80. package/mcp-docs/web/hooks/useTheme.txt +3 -3
  81. package/mcp-docs/web/routes.txt +1 -0
  82. package/package.json +1 -1
@@ -0,0 +1,187 @@
1
+ # Combobox
2
+
3
+ A flexible combobox component for both single and multi-selection, built for mobile applications with comprehensive accessibility support.
4
+
5
+ ## Import
6
+
7
+ ```tsx
8
+ import { Combobox } from '@coinbase/cds-mobile/alpha/combobox'
9
+ ```
10
+
11
+ ## Examples
12
+
13
+ ### A note on search logic
14
+
15
+ We use [fuse.js](https://www.fusejs.io/) to power the fuzzy search logic for Combobox. You can override this search logic with your own using the `filterFunction` prop.
16
+
17
+ ### Multi-Select
18
+
19
+ Basic multi-selection combobox with search.
20
+
21
+ ```jsx
22
+ function MultiSelect() {
23
+ const multiSelectOptions = [
24
+ { value: '1', label: 'Option 1' },
25
+ { value: '2', label: 'Option 2' },
26
+ { value: '3', label: 'Option 3' },
27
+ { value: '4', label: 'Option 4' },
28
+ { value: '5', label: 'Option 5' },
29
+ { value: '6', label: 'Option 6' },
30
+ { value: '7', label: 'Option 7' },
31
+ { value: '8', label: 'Option 8' },
32
+ { value: '9', label: 'Option 9' },
33
+ { value: '10', label: 'Option 10' },
34
+ ];
35
+ const { value, onChange } = useMultiSelect({ initialValue: ['1'] });
36
+
37
+ return (
38
+ <Combobox
39
+ label="Multi Select"
40
+ onChange={onChange}
41
+ options={multiSelectOptions}
42
+ placeholder="Search..."
43
+ type="multi"
44
+ value={value}
45
+ />
46
+ );
47
+ }
48
+ ```
49
+
50
+ ### Single Select
51
+
52
+ Single selection combobox with an option to clear the current choice.
53
+
54
+ ```jsx
55
+ function SingleSelect() {
56
+ const singleSelectOptions = [
57
+ { value: null, label: 'Remove selection' },
58
+ { value: '1', label: 'Option 1' },
59
+ { value: '2', label: 'Option 2' },
60
+ { value: '3', label: 'Option 3' },
61
+ ];
62
+ const [value, setValue] = useState(null);
63
+
64
+ return (
65
+ <Combobox
66
+ label="Single Select"
67
+ onChange={setValue}
68
+ options={singleSelectOptions}
69
+ placeholder="Search..."
70
+ value={value}
71
+ />
72
+ );
73
+ }
74
+ ```
75
+
76
+ ### Controlled Search
77
+
78
+ Manage the search text externally while letting the combobox stay in sync.
79
+
80
+ ```jsx
81
+ function ControlledSearch() {
82
+ const { value, onChange } = useMultiSelect({ initialValue: [] });
83
+ const [searchText, setSearchText] = useState('');
84
+
85
+ const fruitOptions = [
86
+ { value: 'apple', label: 'Apple' },
87
+ { value: 'banana', label: 'Banana' },
88
+ { value: 'cherry', label: 'Cherry' },
89
+ { value: 'date', label: 'Date' },
90
+ ];
91
+
92
+ return (
93
+ <Combobox
94
+ label="Controlled search"
95
+ onChange={onChange}
96
+ onSearch={setSearchText}
97
+ options={fruitOptions}
98
+ placeholder="Type to search..."
99
+ searchText={searchText}
100
+ type="multi"
101
+ value={value}
102
+ />
103
+ );
104
+ }
105
+ ```
106
+
107
+ ### Helper Text
108
+
109
+ Use helper text to guide how many selections a user should make.
110
+
111
+ ```jsx
112
+ function HelperTextExample() {
113
+ const { value, onChange } = useMultiSelect({ initialValue: [] });
114
+
115
+ const teamOptions = [
116
+ { value: 'john', label: 'John Smith', description: 'Engineering' },
117
+ { value: 'jane', label: 'Jane Doe', description: 'Design' },
118
+ { value: 'bob', label: 'Bob Johnson', description: 'Product' },
119
+ { value: 'alice', label: 'Alice Williams', description: 'Engineering' },
120
+ ];
121
+
122
+ return (
123
+ <Combobox
124
+ helperText="Select up to 4 team members"
125
+ label="Team members"
126
+ onChange={onChange}
127
+ options={teamOptions}
128
+ placeholder="Search team members..."
129
+ type="multi"
130
+ value={value}
131
+ />
132
+ );
133
+ }
134
+ ```
135
+
136
+ ## Props
137
+
138
+ | Prop | Type | Required | Default | Description |
139
+ | --- | --- | --- | --- | --- |
140
+ | `onChange` | `(value: Type extends multi ? SelectOptionValue \| SelectOptionValue[] \| null : SelectOptionValue \| null) => void` | Yes | `-` | - |
141
+ | `options` | `SelectOptionList<Type, SelectOptionValue>` | Yes | `-` | Array of options to display in the select dropdown. Can be individual options or groups with label and options |
142
+ | `value` | `string \| SelectOptionValue[] \| null` | Yes | `-` | - |
143
+ | `ComboboxControlComponent` | `ComboboxControlComponent` | No | `-` | - |
144
+ | `ComboboxDropdownComponent` | `SelectDropdownComponent` | No | `-` | - |
145
+ | `SelectAllOptionComponent` | `SelectOptionComponent<Type, SelectOptionValue>` | No | `-` | Custom component to render the Select All option |
146
+ | `SelectControlComponent` | `SelectControlComponent<Type, SelectOptionValue>` | No | `-` | Custom component to render the select control |
147
+ | `SelectDropdownComponent` | `SelectDropdownComponent<Type, SelectOptionValue>` | No | `-` | Custom component to render the dropdown container |
148
+ | `SelectEmptyDropdownContentsComponent` | `SelectEmptyDropdownContentComponent` | No | `-` | Custom component to render when no options are available |
149
+ | `SelectOptionComponent` | `SelectOptionComponent<Type, SelectOptionValue>` | No | `-` | Custom component to render individual options |
150
+ | `SelectOptionGroupComponent` | `SelectOptionGroupComponent<Type, SelectOptionValue>` | No | `-` | Custom component to render group headers |
151
+ | `accessibilityRoles` | `{ option?: AccessibilityRole; } \| undefined` | No | `-` | Accessibility roles for dropdown elements |
152
+ | `accessory` | `ReactElement<CellAccessoryProps, string \| JSXElementConstructor<any>>` | No | `-` | - |
153
+ | `clearAllLabel` | `string` | No | `-` | Label for the Clear All option in multi-select mode |
154
+ | `closeButtonLabel` | `string` | No | `-` | Label for close button when combobox is open (mobile only) |
155
+ | `compact` | `boolean` | No | `-` | Whether to use compact styling for the select |
156
+ | `defaultOpen` | `boolean` | No | `-` | Initial open state when component mounts (uncontrolled mode) |
157
+ | `defaultSearchText` | `string` | No | `-` | Default search text value for uncontrolled mode |
158
+ | `disableClickOutsideClose` | `boolean` | No | `-` | Whether clicking outside the dropdown should close it |
159
+ | `disabled` | `boolean` | No | `false` | Toggles input interactability and opacity |
160
+ | `emptyOptionsLabel` | `string` | No | `-` | Label displayed when there are no options available |
161
+ | `end` | `null \| string \| number \| false \| true \| ReactElement<any, string \| JSXElementConstructor<any>> \| Iterable<ReactNode> \| ReactPortal` | No | `-` | End-aligned content (e.g., value, status). Replaces the deprecated detail prop. |
162
+ | `endNode` | `null \| string \| number \| false \| true \| ReactElement<any, string \| JSXElementConstructor<any>> \| Iterable<ReactNode> \| ReactPortal` | No | `-` | Adds content to the end of the inner input. Refer to diagram for location of endNode in InputStack component |
163
+ | `filterFunction` | `((options: SelectOptionList<Type, SelectOptionValue>, searchText: string) => SelectOption<SelectOptionValue>[])` | No | `-` | Custom filter function for searching options |
164
+ | `helperText` | `null \| string \| number \| false \| true \| ReactElement<any, string \| JSXElementConstructor<any>> \| Iterable<ReactNode> \| ReactPortal` | No | `-` | Helper text displayed below the select |
165
+ | `hiddenSelectedOptionsLabel` | `string` | No | `-` | Label to show for showcasing count of hidden selected options |
166
+ | `hideSearchInput` | `boolean` | No | `-` | Hide the search input |
167
+ | `hideSelectAll` | `boolean` | No | `-` | Whether to hide the Select All option in multi-select mode |
168
+ | `label` | `null \| string \| number \| false \| true \| ReactElement<any, string \| JSXElementConstructor<any>> \| Iterable<ReactNode> \| ReactPortal` | No | `-` | Label displayed above the control |
169
+ | `labelVariant` | `inside \| outside` | No | `'outside'` | The variant of the label. Only used when compact is not true. |
170
+ | `maxSelectedOptionsToShow` | `number` | No | `-` | Maximum number of selected options to show before truncating |
171
+ | `media` | `ReactElement` | No | `-` | Media rendered at the start of the cell (icon, avatar, image, etc). |
172
+ | `onSearch` | `((searchText: string) => void)` | No | `-` | Search text change handler |
173
+ | `open` | `boolean` | No | `-` | Controlled open state of the dropdown |
174
+ | `placeholder` | `null \| string \| number \| false \| true \| ReactElement<any, string \| JSXElementConstructor<any>> \| Iterable<ReactNode> \| ReactPortal` | No | `-` | Placeholder text displayed when no option is selected |
175
+ | `ref` | `null \| (instance: SelectRef \| null) => void \| RefObject<SelectRef>` | No | `-` | - |
176
+ | `removeSelectedOptionAccessibilityLabel` | `string` | No | `-` | Accessibility label for each chip in a multi-select |
177
+ | `searchText` | `string` | No | `-` | Controlled search text value |
178
+ | `selectAllLabel` | `string` | No | `-` | Label for the Select All option in multi-select mode |
179
+ | `setOpen` | `((open: boolean \| ((open: boolean) => boolean)) => void)` | No | `-` | Callback to update the open state |
180
+ | `startNode` | `null \| string \| number \| false \| true \| ReactElement<any, string \| JSXElementConstructor<any>> \| Iterable<ReactNode> \| ReactPortal` | No | `-` | Adds content to the start of the inner input. Refer to diagram for location of startNode in InputStack component |
181
+ | `style` | `null \| false \| ViewStyle \| RegisteredStyle<ViewStyle> \| RecursiveArray<ViewStyle \| Falsy \| RegisteredStyle<ViewStyle>>` | No | `-` | Inline styles for the root element |
182
+ | `styles` | `{ root?: StyleProp<ViewStyle>; control?: StyleProp<ViewStyle>; controlStartNode?: StyleProp<ViewStyle>; controlInputNode?: StyleProp<ViewStyle>; controlValueNode?: StyleProp<ViewStyle>; controlLabelNode?: StyleProp<ViewStyle>; controlHelperTextNode?: StyleProp<ViewStyle>; controlEndNode?: StyleProp<ViewStyle>; controlBlendStyles?: InteractableBlendStyles; dropdown?: StyleProp<ViewStyle>; option?: StyleProp<ViewStyle>; optionCell?: StyleProp<ViewStyle>; optionContent?: StyleProp<ViewStyle>; optionLabel?: StyleProp<ViewStyle>; optionDescription?: StyleProp<ViewStyle>; optionBlendStyles?: InteractableBlendStyles \| undefined; selectAllDivider?: StyleProp<ViewStyle>; emptyContentsContainer?: StyleProp<ViewStyle>; emptyContentsText?: StyleProp<ViewStyle>; optionGroup?: StyleProp<ViewStyle>; } \| undefined` | No | `-` | Custom styles for different parts of the select |
183
+ | `testID` | `string` | No | `-` | Test ID for the root element |
184
+ | `type` | `multi \| single` | No | `-` | Whether the select allows single or multiple selections |
185
+ | `variant` | `primary \| secondary \| positive \| negative \| foregroundMuted \| foreground` | No | `-` | Determines the sentiment of the input. Because we allow startContent and endContent to be custom ReactNode, the content placed inside these slots will not change colors according to the variant. You will have to add that yourself |
186
+
187
+
@@ -23,9 +23,9 @@ function Example() {
23
23
  {
24
24
  title: '$4.15',
25
25
  description: (
26
- <TextLabel2 as="p" color="fgPositive" numberOfLines={2}>
26
+ <Text as="p" font="label2" color="fgPositive" numberOfLines={2}>
27
27
  &#x2197;73.37%
28
- </TextLabel2>
28
+ </Text>
29
29
  ),
30
30
  subtitle: 'ETH',
31
31
  onPress: NoopFn,
@@ -55,9 +55,9 @@ function Example() {
55
55
  {
56
56
  title: '$309.43',
57
57
  description: (
58
- <TextLabel2 as="p" color="fgPositive" numberOfLines={2}>
58
+ <Text as="p" font="label2" color="fgPositive" numberOfLines={2}>
59
59
  &#x2197;3.37%
60
- </TextLabel2>
60
+ </Text>
61
61
  ),
62
62
  subtitle: 'Bitcoin',
63
63
  onPress: NoopFn,
@@ -30,9 +30,9 @@ function Example() {
30
30
  }
31
31
  meta={
32
32
  <Box marginLeft={-1}>
33
- <TextLabel2 as="span" color="fgMuted" marginLeft={-1} numberOfLines={1}>
33
+ <Text as="span" font="label2" color="fgMuted" marginLeft={-1} numberOfLines={1}>
34
34
  ・News・5 hrs
35
- </TextLabel2>
35
+ </Text>
36
36
  </Box>
37
37
  }
38
38
  title="Description"
@@ -41,12 +41,12 @@ function Example() {
41
41
  body="Bitcoin Network Shatters Records With Hashrate Climbing to 464 EH/s"
42
42
  label={
43
43
  <HStack alignItems="flex-end" flexWrap="wrap" gap={0.5}>
44
- <TextLabel2 as="p" color="fgMuted" numberOfLines={1}>
44
+ <Text as="p" font="label2" color="fgMuted" numberOfLines={1}>
45
45
  BTC
46
- </TextLabel2>
47
- <TextLabel2 accessibilityLabel="Up 5.12%" as="p" color="fgPositive">
46
+ </Text>
47
+ <Text font="label2" accessibilityLabel="Up 5.12%" as="p" color="fgPositive">
48
48
  ↗ 5.12%
49
- </TextLabel2>
49
+ </Text>
50
50
  </HStack>
51
51
  }
52
52
  />
@@ -55,9 +55,9 @@ function Example() {
55
55
  <ContentCardHeader
56
56
  meta={
57
57
  <Box marginLeft={-1}>
58
- <TextLabel2 as="span" color="fgMuted" numberOfLines={1}>
58
+ <Text as="span" font="label2" color="fgMuted" numberOfLines={1}>
59
59
  ・News・5 hrs
60
- </TextLabel2>
60
+ </Text>
61
61
  </Box>
62
62
  }
63
63
  title="Brian Armstrong"
@@ -66,12 +66,12 @@ function Example() {
66
66
  body="Bitcoin Network Shatters Records With Hashrate Climbing to 464 EH/s"
67
67
  label={
68
68
  <HStack alignItems="flex-end" flexWrap="wrap" gap={0.5}>
69
- <TextLabel2 as="p" color="fgMuted" numberOfLines={1}>
69
+ <Text as="p" font="label2" color="fgMuted" numberOfLines={1}>
70
70
  BTC
71
- </TextLabel2>
72
- <TextLabel2 accessibilityLabel="Up 5.12%" as="p" color="fgPositive">
71
+ </Text>
72
+ <Text font="label2" accessibilityLabel="Up 5.12%" as="p" color="fgPositive">
73
73
  ↗ 5.12%
74
- </TextLabel2>
74
+ </Text>
75
75
  </HStack>
76
76
  }
77
77
  media={
@@ -130,18 +130,18 @@ function Example() {
130
130
  <ContentCard gap={3}>
131
131
  <ContentCardBody
132
132
  body={
133
- <TextBody as="p" paddingTop={0.5}>
133
+ <Text as="p" font="body" paddingTop={0.5}>
134
134
  Bitcoin Network Shatters Records With Hashrate Climbing to 464 EH/s
135
- </TextBody>
135
+ </Text>
136
136
  }
137
137
  label={
138
138
  <HStack alignItems="flex-end" flexWrap="wrap" gap={0.5}>
139
- <TextLabel2 as="p" color="fgMuted" numberOfLines={1}>
139
+ <Text as="p" font="label2" color="fgMuted" numberOfLines={1}>
140
140
  BTC
141
- </TextLabel2>
142
- <TextLabel2 accessibilityLabel="Up 5.12%" as="p" color="fgPositive">
141
+ </Text>
142
+ <Text font="label2" accessibilityLabel="Up 5.12%" as="p" color="fgPositive">
143
143
  ↗ 5.12%
144
- </TextLabel2>
144
+ </Text>
145
145
  </HStack>
146
146
  }
147
147
  media={
@@ -165,7 +165,9 @@ function Example() {
165
165
  <TextLegal as="span" color="fgMuted">
166
166
  Reward
167
167
  </TextLegal>
168
- <TextHeadline as="span">+$15 ACS</TextHeadline>
168
+ <Text as="span" font="headline">
169
+ +$15 ACS
170
+ </Text>
169
171
  </VStack>
170
172
  </HStack>
171
173
  <Button compact accessibilityLabel="Claim now" variant="secondary">
@@ -203,9 +205,9 @@ function Example() {
203
205
  }
204
206
  meta={
205
207
  <Box marginLeft={-1}>
206
- <TextLabel2 as="span" color="fgMuted" numberOfLines={1}>
208
+ <Text as="span" font="label2" color="fgMuted" numberOfLines={1}>
207
209
  @matdryhurst・7 mo
208
- </TextLabel2>
210
+ </Text>
209
211
  </Box>
210
212
  }
211
213
  title="Mat Dryhurst"
@@ -220,9 +222,9 @@ function Example() {
220
222
  avatar="/img/card/content_card_custom_avatar_1.png"
221
223
  meta={
222
224
  <Box marginLeft={-1}>
223
- <TextLabel2 as="span" color="fgMuted" numberOfLines={1}>
225
+ <Text as="span" font="label2" color="fgMuted" numberOfLines={1}>
224
226
  ・News・5 hrs
225
- </TextLabel2>
227
+ </Text>
226
228
  </Box>
227
229
  }
228
230
  title="Description"
@@ -240,12 +242,12 @@ function Example() {
240
242
  gap={1.5}
241
243
  label={
242
244
  <HStack alignItems="flex-end" flexWrap="wrap" gap={0.5}>
243
- <TextLabel2 as="p" color="fgMuted" numberOfLines={1}>
245
+ <Text as="p" font="label2" color="fgMuted" numberOfLines={1}>
244
246
  BTC
245
- </TextLabel2>
246
- <TextLabel2 accessibilityLabel="Up 5.12%" as="p" color="fgPositive">
247
+ </Text>
248
+ <Text font="label2" accessibilityLabel="Up 5.12%" as="p" color="fgPositive">
247
249
  ↗ 5.12%
248
- </TextLabel2>
250
+ </Text>
249
251
  </HStack>
250
252
  }
251
253
  paddingBottom={3}
@@ -18,12 +18,12 @@ import { ContentCardBody } from '@coinbase/cds-mobile/cards/ContentCard'
18
18
  body="Bitcoin Network Shatters Records With Hashrate Climbing to 464 EH/s"
19
19
  label={
20
20
  <HStack alignItems="flex-end" flexWrap="wrap" gap={0.5}>
21
- <TextLabel2 as="p" color="fgMuted" numberOfLines={1}>
21
+ <Text as="p" font="label2" color="fgMuted" numberOfLines={1}>
22
22
  BTC
23
- </TextLabel2>
24
- <TextLabel2 accessibilityLabel="Up 5.12%" as="p" color="fgPositive">
23
+ </Text>
24
+ <Text font="label2" accessibilityLabel="Up 5.12%" as="p" color="fgPositive">
25
25
  ↗ 5.12%
26
- </TextLabel2>
26
+ </Text>
27
27
  </HStack>
28
28
  }
29
29
  />
@@ -20,9 +20,9 @@ function Example() {
20
20
  avatar="/img/card/content_card_custom_avatar_1.png"
21
21
  meta={
22
22
  <Box marginLeft={-1}>
23
- <TextLabel2 as="span" color="fgMuted" numberOfLines={1}>
23
+ <Text as="span" font="label2" color="fgMuted" numberOfLines={1}>
24
24
  ・News・5 hrs
25
- </TextLabel2>
25
+ </Text>
26
26
  </Box>
27
27
  }
28
28
  title="Description"
@@ -58,9 +58,9 @@ function Example() {
58
58
  {
59
59
  title: '#7560',
60
60
  description: (
61
- <TextLabel2 color="fgPositive" numberOfLines={2}>
61
+ <Text font="label2" color="fgPositive" numberOfLines={2}>
62
62
  &#x2197;6.37%
63
- </TextLabel2>
63
+ </Text>
64
64
  ),
65
65
  subtitle: 'Bored Ape',
66
66
  onPress: NoopFn,
@@ -76,9 +76,9 @@ function Example() {
76
76
  {
77
77
  title: '#2015',
78
78
  description: (
79
- <TextLabel2 color="fgNegative" numberOfLines={2}>
79
+ <Text font="label2" color="fgNegative" numberOfLines={2}>
80
80
  &#x2198;6.37%
81
- </TextLabel2>
81
+ </Text>
82
82
  ),
83
83
  subtitle: 'Pudgy Penguins',
84
84
  onPress: NoopFn,
@@ -115,9 +115,9 @@ function Example() {
115
115
  {
116
116
  title: 'Parallel',
117
117
  description: (
118
- <TextLabel2 color="fgMuted" numberOfLines={2}>
118
+ <Text font="label2" color="fgMuted" numberOfLines={2}>
119
119
  &#9733;4.5
120
- </TextLabel2>
120
+ </Text>
121
121
  ),
122
122
  onPress: NoopFn,
123
123
  media: (
@@ -10,19 +10,23 @@ import { IconButton } from '@coinbase/cds-mobile/buttons/IconButton'
10
10
 
11
11
  ## Examples
12
12
 
13
- Icon buttons must have a name (which determines the icon), and can use variants to denote intent and importance.
13
+ IconButton is a compact button that displays only an icon. Use it for actions where the icon alone clearly communicates the purpose.
14
14
 
15
- :::tip Accessibility tip
15
+ ### Basics
16
16
 
17
- To ensure your `IconButton` implementation is accessible, it must have an `accessibilityLabel` that describes the purpose of the button.
17
+ The only required props are `name` (which determines the icon) and `accessibilityLabel` (for screen readers).
18
18
 
19
- <br />
19
+ ```jsx
20
+ <HStack gap={2}>
21
+ <IconButton name="gear" accessibilityLabel="Open settings" onPress={console.log} />
22
+ <IconButton name="close" accessibilityLabel="Close modal" onPress={console.log} />
23
+ <IconButton name="refresh" accessibilityLabel="Refresh data" onPress={console.log} />
24
+ </HStack>
25
+ ```
20
26
 
21
- In cases where you're composing a button next to a label or some text that describes the buttons
22
- action, you can setup your system using `accessibilityLabelledBy` prop mapping to the `id` on the
23
- label node (See [Composed example](#composed-example)).
27
+ ### Variants
24
28
 
25
- :::
29
+ Use variants to denote intent and importance. The `active` prop fills the icon when enabled.
26
30
 
27
31
  ```jsx
28
32
  <HStack gap={2}>
@@ -42,7 +46,7 @@ label node (See [Composed example](#composed-example)).
42
46
  />
43
47
  <IconButton
44
48
  name="phone"
45
- accessibilityLabel="View settings"
49
+ accessibilityLabel="Call support"
46
50
  variant="tertiary"
47
51
  onPress={console.log}
48
52
  />
@@ -55,54 +59,107 @@ label node (See [Composed example](#composed-example)).
55
59
  </HStack>
56
60
  ```
57
61
 
58
- ### Transparent variant
62
+ #### Transparent
59
63
 
60
- Use the `transparent` prop to make the background and border transparent until the user interacts with the button.
64
+ Use the `transparent` prop to remove the background until the user interacts with the button.
61
65
 
62
66
  ```jsx
63
- <IconButton
64
- active
65
- name="orderHistory"
66
- accessibilityLabel="View past order history"
67
- variant="primary"
68
- transparent
69
- onPress={console.log}
70
- />
67
+ <HStack gap={2}>
68
+ <IconButton
69
+ active
70
+ name="orderHistory"
71
+ accessibilityLabel="View past order history"
72
+ variant="primary"
73
+ transparent
74
+ onPress={console.log}
75
+ />
76
+ <IconButton
77
+ active
78
+ name="gear"
79
+ accessibilityLabel="Update settings"
80
+ variant="secondary"
81
+ transparent
82
+ onPress={console.log}
83
+ />
84
+ <IconButton
85
+ name="phone"
86
+ accessibilityLabel="Call support"
87
+ variant="tertiary"
88
+ transparent
89
+ onPress={console.log}
90
+ />
91
+ <IconButton
92
+ name="checkmark"
93
+ accessibilityLabel="Verify your identity"
94
+ variant="foregroundMuted"
95
+ transparent
96
+ onPress={console.log}
97
+ />
98
+ </HStack>
71
99
  ```
72
100
 
73
- ### Loading state
101
+ ### States
102
+
103
+ #### Loading
74
104
 
75
- Use the `loading` prop to show a spinner and make the button non-interactive during async operations.
105
+ Use the `loading` prop to show a spinner when an action is in progress. The button becomes non-interactive and displays a loading spinner instead of the icon.
76
106
 
77
107
  ```jsx
78
- <IconButton
79
- active
80
- name="orderHistory"
81
- accessibilityLabel="Loading transaction history"
82
- variant="primary"
83
- loading
84
- onPress={console.log}
85
- />
108
+ <HStack gap={2}>
109
+ <IconButton
110
+ active
111
+ name="orderHistory"
112
+ accessibilityLabel="Loading transaction history"
113
+ variant="primary"
114
+ loading
115
+ onPress={console.log}
116
+ />
117
+ <IconButton
118
+ active
119
+ name="gear"
120
+ accessibilityLabel="Loading settings"
121
+ variant="secondary"
122
+ loading
123
+ onPress={console.log}
124
+ />
125
+ </HStack>
86
126
  ```
87
127
 
88
- ### Disabled state
128
+ #### Disabled
89
129
 
90
130
  Use the `disabled` prop to prevent interaction and show a disabled visual state.
91
131
 
92
132
  ```jsx
93
- <IconButton
94
- active
95
- name="orderHistory"
96
- accessibilityLabel="View transaction history"
97
- variant="primary"
98
- disabled
99
- onPress={console.log}
100
- />
133
+ <HStack gap={2}>
134
+ <IconButton
135
+ active
136
+ name="orderHistory"
137
+ accessibilityLabel="View transaction history"
138
+ variant="primary"
139
+ disabled
140
+ onPress={console.log}
141
+ />
142
+ <IconButton
143
+ active
144
+ name="gear"
145
+ accessibilityLabel="View settings"
146
+ variant="secondary"
147
+ disabled
148
+ onPress={console.log}
149
+ />
150
+ <IconButton
151
+ name="checkmark"
152
+ accessibilityLabel="Approve transaction"
153
+ variant="foregroundMuted"
154
+ disabled
155
+ onPress={console.log}
156
+ />
157
+ </HStack>
101
158
  ```
102
159
 
103
160
  ### Sizing
104
161
 
105
- IconButtons are compact by default. Set the `compact` prop to `false` for larger touch targets.
162
+ IconButtons are compact by default. Use `compact={false}` for larger touch targets.
106
163
 
107
164
  ```jsx
108
165
  <HStack gap={2} alignItems="center">
@@ -125,28 +182,39 @@ IconButtons are compact by default. Set the `compact` prop to `false` for larger
125
182
  </HStack>
126
183
  ```
127
184
 
128
- ### Composed example
185
+ ### Accessibility
129
186
 
130
- As referenced above, if you're building a composed system, use the `accessibilityLabelledBy` prop and an `id` on the text node.
187
+ Since icon buttons have no visible text, an `accessibilityLabel` is required to describe the button's purpose for screen readers.
131
188
 
132
189
  ```jsx
133
- function composedExample() {
190
+ <IconButton name="close" accessibilityLabel="Close trade modal" />
191
+ ```
192
+
193
+ When composing a button with a visible label, use `accessibilityLabelledBy` to reference the label's `id` instead. See the [Claim Drop example](#claim-drop) below.
194
+
195
+ ### Composed Examples
196
+
197
+ #### Claim Drop
198
+
199
+ A toggleable icon button with an adjacent label. Uses `accessibilityLabelledBy` to associate the button with its visible label.
200
+
201
+ ```jsx
202
+ function ClaimDropExample() {
134
203
  const [active, setActive] = useState(false);
135
- const name = useMemo(() => (active ? 'dropsActive' : 'dropsInactive'), [active]);
136
204
  const variant = useMemo(() => (active ? 'primary' : 'foregroundMuted'), [active]);
137
205
  const label = useMemo(() => (active ? 'Reject drop' : 'Claim drop'), [active]);
138
206
 
139
207
  return (
140
208
  <HStack gap={2} alignItems="center">
141
209
  <IconButton
142
- name={name}
210
+ name="drops"
211
+ active={active}
143
212
  variant={variant}
144
213
  onPress={() => setActive((active) => !active)}
145
- // Accessibility props
146
- id="my-icon--id"
147
- accessibilityLabelledBy="my-label--id"
214
+ id="claim-drop-button"
215
+ accessibilityLabelledBy="claim-drop-label"
148
216
  />
149
- <Text font="label1" as="label" htmlFor="my-icon--id" id="my-label--id">
217
+ <Text font="label1" id="claim-drop-label">
150
218
  {label}
151
219
  </Text>
152
220
  </HStack>
@@ -154,12 +222,19 @@ function composedExample() {
154
222
  }
155
223
  ```
156
224
 
157
- ### A11y
225
+ #### Notification Bell
158
226
 
159
- Since icon buttons have no descriptive text or children, an accessibility label must be provided.
227
+ An icon button with a badge showing the notification count. Uses `DotCount` to display the number of unread notifications.
160
228
 
161
229
  ```jsx
162
- <IconButton name="close" accessibilityLabel="Close trade modal" />
230
+ <DotCount count={3} overlap="circular" pin="top-end">
231
+ <IconButton
232
+ name="bell"
233
+ accessibilityLabel="Notifications, 3 unread"
234
+ variant="secondary"
235
+ onPress={console.log}
236
+ />
237
+ </DotCount>
163
238
  ```
164
239
 
165
240
  ## Props