@coinbase/cds-mcp-server 8.25.1 → 8.27.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.
@@ -77,6 +77,7 @@
77
77
  - [Switch](mobile/components/Switch.txt): A control for toggling between on and off.
78
78
  - [SlideButton](mobile/components/SlideButton.txt): A button that slides to confirm an action.
79
79
  - [SelectOption](mobile/components/SelectOption.txt): A single option of a Select component.
80
+ - [SelectChipAlpha](mobile/components/SelectChipAlpha.txt): A chip-styled Select control built on top of the Alpha Select component. Supports both single and multi selection.
80
81
  - [SelectChip](mobile/components/SelectChip.txt): A Chip and Select control for selecting from a list of options
81
82
  - [SelectAlpha](mobile/components/SelectAlpha.txt): A flexible select component for both single and multi-selection, built for mobile applications with comprehensive accessibility support.
82
83
  - [Select](mobile/components/Select.txt): A control for selecting from a list of options.
@@ -96,7 +96,7 @@ The ContentCellFallback component provides loading state representations of Cont
96
96
 
97
97
  | Prop | Type | Required | Default | Description |
98
98
  | --- | --- | --- | --- | --- |
99
- | `accessory` | `more \| selected \| arrow` | No | `-` | Accessory to display at the end of the cell. |
99
+ | `accessory` | `more \| selected \| arrow \| unselected` | No | `-` | Accessory to display at the end of the cell. |
100
100
  | `accessoryNode` | `null \| string \| number \| false \| true \| ReactElement<any, string \| JSXElementConstructor<any>> \| Iterable<ReactNode> \| ReactPortal` | No | `-` | Custom accessory node rendered at the end of the cell. Takes precedence over accessory. |
101
101
  | `alignContent` | `ResponsiveProp<center \| normal \| start \| end \| flex-start \| flex-end \| stretch \| baseline \| first baseline \| last baseline \| space-between \| space-around \| space-evenly>` | No | `-` | - |
102
102
  | `alignItems` | `ResponsiveProp<center \| normal \| start \| end \| flex-start \| flex-end \| self-start \| self-end \| stretch \| baseline \| first baseline \| last baseline>` | No | `-` | - |
@@ -294,6 +294,29 @@ When you pass the `end` prop, it overrides the `detail`/`subdetail`/`detailNode`
294
294
  />
295
295
  ```
296
296
 
297
+ #### Preserve Layout During Selection
298
+
299
+ Use the `unselected` accessory to reserve space for the selection checkmark when toggling the `selected` state.
300
+
301
+ ```tsx live
302
+ function PreserveLayoutExample() {
303
+ const [isSelected, setIsSelected] = useState(false);
304
+
305
+ return (
306
+ <VStack gap={1}>
307
+ <ListCell
308
+ accessory={isSelected ? 'selected' : 'unselected'}
309
+ description="Selected state uses the same space, no layout shift when selected"
310
+ spacingVariant="condensed"
311
+ title="Leverage unselected state"
312
+ selected={isSelected}
313
+ onClick={() => setIsSelected((prev) => !prev)}
314
+ />
315
+ </VStack>
316
+ );
317
+ }
318
+ ```
319
+
297
320
  #### Custom Accessory via Node Prop
298
321
 
299
322
  ```tsx live
@@ -571,7 +594,7 @@ Mapping to `styles` / `classNames` keys:
571
594
 
572
595
  | Prop | Type | Required | Default | Description |
573
596
  | --- | --- | --- | --- | --- |
574
- | `accessory` | `more \| selected \| arrow` | No | `-` | Accessory to display at the end of the cell. |
597
+ | `accessory` | `more \| selected \| arrow \| unselected` | No | `-` | Accessory to display at the end of the cell. |
575
598
  | `accessoryNode` | `null \| string \| number \| false \| true \| ReactElement<any, string \| JSXElementConstructor<any>> \| Iterable<ReactNode> \| ReactPortal` | No | `-` | Custom accessory node rendered at the end of the cell. Takes precedence over accessory. |
576
599
  | `action` | `null \| string \| number \| false \| true \| ReactElement<any, string \| JSXElementConstructor<any>> \| Iterable<ReactNode> \| ReactPortal` | No | `-` | - |
577
600
  | `alignContent` | `ResponsiveProp<center \| normal \| start \| end \| flex-start \| flex-end \| stretch \| baseline \| first baseline \| last baseline \| space-between \| space-around \| space-evenly>` | No | `-` | - |
@@ -581,7 +581,7 @@ function DraggablePriceTarget() {
581
581
  | `beaconLabelMinGap` | `number` | No | `-` | Minimum gap between beacon labels to prevent overlap. Measured in pixels. |
582
582
  | `beaconTransitions` | `{ update?: Transition$1; pulse?: Transition$1 \| undefined; pulseRepeatDelay?: number \| undefined; } \| undefined` | No | `-` | Transition configuration for the scrubber beacon. |
583
583
  | `classNames` | `{ overlay?: string; beacon?: string \| undefined; line?: string \| undefined; beaconLabel?: string \| undefined; } \| undefined` | No | `-` | Custom class names for scrubber elements. |
584
- | `hideLine` | `boolean` | No | `-` | Hides the scrubber line |
584
+ | `hideLine` | `boolean` | No | `-` | Hides the scrubber line. |
585
585
  | `hideOverlay` | `boolean` | No | `-` | Hides the overlay rect which obscures data beyond the scrubber position. |
586
586
  | `idlePulse` | `boolean` | No | `-` | Pulse the beacons while at rest. |
587
587
  | `key` | `Key \| null` | No | `-` | - |
@@ -608,7 +608,7 @@ By default, Scrubber will show an overlay to de-emphasize future data. You can h
608
608
  | `beaconLabelMinGap` | `number` | No | `-` | Minimum gap between beacon labels to prevent overlap. Measured in pixels. |
609
609
  | `beaconTransitions` | `{ update?: Transition$1; pulse?: Transition$1 \| undefined; pulseRepeatDelay?: number \| undefined; } \| undefined` | No | `-` | Transition configuration for the scrubber beacon. |
610
610
  | `classNames` | `{ overlay?: string; beacon?: string \| undefined; line?: string \| undefined; beaconLabel?: string \| undefined; } \| undefined` | No | `-` | Custom class names for scrubber elements. |
611
- | `hideLine` | `boolean` | No | `-` | Hides the scrubber line |
611
+ | `hideLine` | `boolean` | No | `-` | Hides the scrubber line. |
612
612
  | `hideOverlay` | `boolean` | No | `-` | Hides the overlay rect which obscures data beyond the scrubber position. |
613
613
  | `idlePulse` | `boolean` | No | `-` | Pulse the beacons while at rest. |
614
614
  | `key` | `Key \| null` | No | `-` | - |
@@ -10,6 +10,10 @@ import { Select } from '@coinbase/cds-web/alpha/select'
10
10
 
11
11
  ## Examples
12
12
 
13
+ :::note Duplicate Values
14
+ Avoid using options with duplicate values. Each option's `value` should be unique within the options array to ensure proper selection behavior.
15
+ :::
16
+
13
17
  ### Single Select
14
18
 
15
19
  Basic single selection with predefined options.
@@ -41,6 +45,10 @@ function SingleSelectExample() {
41
45
 
42
46
  Multi-selection mode allows users to select multiple options from the list.
43
47
 
48
+ :::note Disabled Options and Select All
49
+ Disabled options and options inside disabled groups will be skipped when "Select all" is pressed. Only enabled options will be selected.
50
+ :::
51
+
44
52
  ```jsx live
45
53
  function MultiSelectExample() {
46
54
  const { value, onChange } = useMultiSelect({
@@ -76,6 +84,95 @@ function MultiSelectExample() {
76
84
  }
77
85
  ```
78
86
 
87
+ ### Single Select with Groups
88
+
89
+ Organize options into logical groups for better organization.
90
+
91
+ ```jsx live
92
+ function SingleSelectWithGroupsExample() {
93
+ const [value, setValue] = useState(null);
94
+
95
+ const groupedOptions = [
96
+ {
97
+ label: 'Group A',
98
+ options: [
99
+ { value: '1', label: 'Option 1' },
100
+ { value: '2', label: 'Option 2' },
101
+ { value: '3', label: 'Option 3' },
102
+ ],
103
+ },
104
+ {
105
+ label: 'Group B',
106
+ options: [
107
+ { value: '4', label: 'Option 4' },
108
+ { value: '5', label: 'Option 5' },
109
+ ],
110
+ },
111
+ {
112
+ label: 'Group C',
113
+ options: [{ value: '6', label: 'Option 6' }],
114
+ },
115
+ ];
116
+
117
+ return (
118
+ <Select
119
+ label="Choose an option"
120
+ value={value}
121
+ onChange={setValue}
122
+ options={groupedOptions}
123
+ placeholder="Select an option"
124
+ />
125
+ );
126
+ }
127
+ ```
128
+
129
+ ### Multi-Select with Groups
130
+
131
+ Use groups in multi-select mode to organize selections.
132
+
133
+ ```jsx live
134
+ function MultiSelectWithGroupsExample() {
135
+ const { value, onChange } = useMultiSelect({
136
+ initialValue: [],
137
+ });
138
+
139
+ const groupedOptions = [
140
+ {
141
+ label: 'Group A',
142
+ options: [
143
+ { value: '1', label: 'Option 1' },
144
+ { value: '2', label: 'Option 2' },
145
+ { value: '3', label: 'Option 3' },
146
+ ],
147
+ },
148
+ {
149
+ label: 'Group B',
150
+ options: [
151
+ { value: '4', label: 'Option 4' },
152
+ { value: '5', label: 'Option 5' },
153
+ ],
154
+ },
155
+ {
156
+ label: 'Group C',
157
+ options: [{ value: '6', label: 'Option 6' }],
158
+ },
159
+ ];
160
+
161
+ return (
162
+ <Select
163
+ type="multi"
164
+ label="Choose multiple options"
165
+ value={value}
166
+ onChange={onChange}
167
+ options={groupedOptions}
168
+ placeholder="Select options"
169
+ selectAllLabel="Select all options"
170
+ clearAllLabel="Clear all selections"
171
+ />
172
+ );
173
+ }
174
+ ```
175
+
79
176
  ### Accessibility Props
80
177
 
81
178
  The Select component supports comprehensive accessibility features including custom labels and roles.
@@ -155,6 +252,53 @@ function VariantExample() {
155
252
  }
156
253
  ```
157
254
 
255
+ ### With Disabled Option Group
256
+
257
+ Disable entire groups to prevent selection of those options.
258
+
259
+ ```jsx live
260
+ function DisabledGroupExample() {
261
+ const [value, setValue] = useState(null);
262
+
263
+ const groupedOptions = [
264
+ {
265
+ label: 'Available Options',
266
+ options: [
267
+ { value: '1', label: 'Option 1' },
268
+ { value: '2', label: 'Option 2' },
269
+ { value: '3', label: 'Option 3' },
270
+ ],
271
+ },
272
+ {
273
+ label: 'Unavailable Options (Group Disabled)',
274
+ disabled: true,
275
+ options: [
276
+ { value: '4', label: 'Option 4' },
277
+ { value: '5', label: 'Option 5' },
278
+ { value: '6', label: 'Option 6' },
279
+ ],
280
+ },
281
+ {
282
+ label: 'More Available Options',
283
+ options: [
284
+ { value: '7', label: 'Option 7' },
285
+ { value: '8', label: 'Option 8' },
286
+ ],
287
+ },
288
+ ];
289
+
290
+ return (
291
+ <Select
292
+ label="Choose an option"
293
+ value={value}
294
+ onChange={setValue}
295
+ options={groupedOptions}
296
+ placeholder="Select an option"
297
+ />
298
+ );
299
+ }
300
+ ```
301
+
158
302
  ### Compact Mode
159
303
 
160
304
  The Select component can be rendered in a compact size for denser UIs.
@@ -1142,45 +1286,5 @@ function CustomComponentExamples() {
1142
1286
 
1143
1287
  | Prop | Type | Required | Default | Description |
1144
1288
  | --- | --- | --- | --- | --- |
1145
- | `onChange` | `(value: Type extends multi ? SelectOptionValue \| SelectOptionValue[] \| null : SelectOptionValue \| null) => void` | Yes | `-` | - |
1146
- | `options` | `(SelectOption<SelectOptionValue> & Pick<SelectOptionProps<Type, string>, media \| end \| accessory> & { Component?: SelectOptionComponent<Type, SelectOptionValue> \| undefined; })[]` | Yes | `-` | Array of options to display in the select dropdown |
1147
- | `value` | `string \| SelectOptionValue[] \| null` | Yes | `-` | - |
1148
- | `SelectAllOptionComponent` | `SelectOptionComponent<Type, SelectOptionValue>` | No | `-` | Custom component to render the Select All option |
1149
- | `SelectControlComponent` | `SelectControlComponent<Type, SelectOptionValue>` | No | `-` | Custom component to render the select control |
1150
- | `SelectDropdownComponent` | `SelectDropdownComponent<Type, SelectOptionValue>` | No | `-` | Custom component to render the dropdown container |
1151
- | `SelectEmptyDropdownContentsComponent` | `SelectEmptyDropdownContentComponent` | No | `-` | Custom component to render when no options are available |
1152
- | `SelectOptionComponent` | `SelectOptionComponent<Type, SelectOptionValue>` | No | `-` | Custom component to render individual options |
1153
- | `accessibilityRoles` | `{ dropdown?: AriaHasPopupType; option?: string \| undefined; } \| undefined` | No | `-` | Accessibility roles for dropdown and option elements |
1154
- | `accessory` | `ReactElement<CellAccessoryProps, string \| JSXElementConstructor<any>>` | No | `-` | Accessory element rendered at the end of the cell (e.g., chevron). |
1155
- | `className` | `string` | No | `-` | CSS class name for the root element |
1156
- | `classNames` | `{ root?: string; control?: string \| undefined; controlStartNode?: string \| undefined; controlInputNode?: string \| undefined; controlValueNode?: string \| undefined; controlLabelNode?: string \| undefined; controlHelperTextNode?: string \| undefined; controlEndNode?: string \| undefined; dropdown?: string \| undefined; option?: string \| undefined; optionCell?: string \| undefined; optionContent?: string \| undefined; optionLabel?: string \| undefined; optionDescription?: string \| undefined; selectAllDivider?: string \| undefined; emptyContentsContainer?: string \| undefined; emptyContentsText?: string \| undefined; } \| undefined` | No | `-` | Custom class names for different parts of the select |
1157
- | `clearAllLabel` | `string` | No | `-` | Label for the Clear All option in multi-select mode |
1158
- | `compact` | `boolean` | No | `-` | Whether to use compact styling for the select |
1159
- | `controlAccessibilityLabel` | `string` | No | `-` | Accessibility label for the control |
1160
- | `defaultOpen` | `boolean` | No | `-` | Initial open state when component mounts (uncontrolled mode) |
1161
- | `disableClickOutsideClose` | `boolean` | No | `-` | Whether clicking outside the dropdown should close it |
1162
- | `disabled` | `boolean` | No | `false` | Toggles input interactability and opacity |
1163
- | `emptyOptionsLabel` | `string` | No | `-` | Label displayed when there are no options available |
1164
- | `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. |
1165
- | `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 |
1166
- | `helperText` | `null \| string \| number \| false \| true \| ReactElement<any, string \| JSXElementConstructor<any>> \| Iterable<ReactNode> \| ReactPortal` | No | `-` | Helper text displayed below the select |
1167
- | `hiddenSelectedOptionsLabel` | `string` | No | `-` | Label to show for showcasing count of hidden selected options |
1168
- | `hideSelectAll` | `boolean` | No | `-` | Whether to hide the Select All option in multi-select mode |
1169
- | `label` | `null \| string \| number \| false \| true \| ReactElement<any, string \| JSXElementConstructor<any>> \| Iterable<ReactNode> \| ReactPortal` | No | `-` | Label displayed above the control |
1170
- | `labelVariant` | `inside \| outside` | No | `'outside'` | The variant of the label. Only used when compact is not true. |
1171
- | `maxSelectedOptionsToShow` | `number` | No | `-` | Maximum number of selected options to show before truncating |
1172
- | `media` | `ReactElement` | No | `-` | Media rendered at the start of the cell (icon, avatar, image, etc). |
1173
- | `open` | `boolean` | No | `-` | Controlled open state of the dropdown |
1174
- | `placeholder` | `null \| string \| number \| false \| true \| ReactElement<any, string \| JSXElementConstructor<any>> \| Iterable<ReactNode> \| ReactPortal` | No | `-` | Placeholder text displayed when no option is selected |
1175
- | `ref` | `null \| (instance: SelectRef \| null) => void \| RefObject<SelectRef>` | No | `-` | - |
1176
- | `removeSelectedOptionAccessibilityLabel` | `string` | No | `-` | Accessibility label for each chip in a multi-select |
1177
- | `selectAllLabel` | `string` | No | `-` | Label for the Select All option in multi-select mode |
1178
- | `setOpen` | `((open: boolean \| ((open: boolean) => boolean)) => void)` | No | `-` | Callback to update the open state |
1179
- | `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 |
1180
- | `style` | `CSSProperties` | No | `-` | Inline styles for the root element |
1181
- | `styles` | `{ root?: CSSProperties; control?: CSSProperties \| undefined; controlStartNode?: CSSProperties \| undefined; controlInputNode?: CSSProperties \| undefined; controlValueNode?: CSSProperties \| undefined; controlLabelNode?: CSSProperties \| undefined; controlHelperTextNode?: CSSProperties \| undefined; controlEndNode?: CSSProperties \| undefined; controlBlendStyles?: InteractableBlendStyles \| undefined; dropdown?: CSSProperties \| undefined; option?: CSSProperties \| undefined; optionCell?: CSSProperties \| undefined; optionContent?: CSSProperties \| undefined; optionLabel?: CSSProperties \| undefined; optionDescription?: CSSProperties \| undefined; optionBlendStyles?: InteractableBlendStyles \| undefined; selectAllDivider?: CSSProperties \| undefined; emptyContentsContainer?: CSSProperties \| undefined; emptyContentsText?: CSSProperties \| undefined; } \| undefined` | No | `-` | Custom styles for different parts of the select |
1182
- | `testID` | `string` | No | `-` | Test ID for the root element |
1183
- | `type` | `single \| multi` | No | `-` | Whether the select allows single or multiple selections |
1184
- | `variant` | `primary \| secondary \| positive \| negative \| foregroundMuted \| foreground` | No | `foregroundMuted` | 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 |
1185
1289
 
1186
1290
 
@@ -37,7 +37,7 @@ function SelectChipExample() {
37
37
  );
38
38
  return (
39
39
  <HStack>
40
- <SelectChip value={value} onChange={setValue} content={content} minWidth={367} />
40
+ <OldSelectChip value={value} onChange={setValue} content={content} minWidth={367} />
41
41
  </HStack>
42
42
  );
43
43
  }
@@ -60,7 +60,7 @@ function SelectChipExample() {
60
60
  );
61
61
  return (
62
62
  <HStack>
63
- <SelectChip value={value} onChange={setValue} content={content} minWidth={150} />
63
+ <OldSelectChip value={value} onChange={setValue} content={content} minWidth={150} />
64
64
  </HStack>
65
65
  );
66
66
  }
@@ -107,7 +107,7 @@ function SelectChipExample() {
107
107
  );
108
108
  return (
109
109
  <HStack>
110
- <SelectChip
110
+ <OldSelectChip
111
111
  placeholder="Networks"
112
112
  value={value ? value.value : undefined}
113
113
  valueLabel={value ? value.title : undefined}
@@ -166,7 +166,7 @@ function SelectChipExample() {
166
166
  );
167
167
  return (
168
168
  <HStack>
169
- <SelectChip
169
+ <OldSelectChip
170
170
  value={value.value}
171
171
  valueLabel={value.label}
172
172
  end={<Icon size="s" color="fg" name={value.iconName} />}