@coinbase/cds-mcp-server 8.28.0 → 8.28.2

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.
package/CHANGELOG.md CHANGED
@@ -8,6 +8,14 @@ All notable changes to this project will be documented in this file.
8
8
 
9
9
  <!-- template-start -->
10
10
 
11
+ ## 8.28.2 ((12/12/2025, 06:23 AM PST))
12
+
13
+ This is an artificial version bump with no new change.
14
+
15
+ ## 8.28.1 ((12/10/2025, 04:33 PM PST))
16
+
17
+ This is an artificial version bump with no new change.
18
+
11
19
  ## 8.28.0 ((12/10/2025, 03:41 PM PST))
12
20
 
13
21
  This is an artificial version bump with no new change.
@@ -10,79 +10,222 @@ import { Button } from '@coinbase/cds-mobile/buttons/Button'
10
10
 
11
11
  ## Examples
12
12
 
13
- ### Primary Button
13
+ Buttons allow users to take actions and make choices with a single tap. They communicate what action will occur when the user interacts with them.
14
14
 
15
- Use primary buttons for high emphasis actions. These buttons have the most visual impact and should be reserved for the most important, final actions that complete a flow, like Save, Join now, or Confirm. Try to use one per screen. Multiple primary buttons make it confusing for the user to understand what action they should take.
15
+ ### Basics
16
+
17
+ The only required prop is `children`, which is the button's label. Buttons default to the `primary` variant.
16
18
 
17
19
  ```jsx
18
- <Button onPress={console.log} variant="primary">
19
- Primary
20
- </Button>
20
+ <Button onPress={console.log}>Get started</Button>
21
21
  ```
22
22
 
23
- ### Secondary Button
23
+ ### Variants
24
24
 
25
- These buttons have a medium level of emphasis that should be used for non-critical actions. Secondary buttons can be used on pages without restrictions and works well for multiple actions of equal weight. They can be used in conjunction with a Primary Button or independently.
25
+ Use variants to communicate the importance and intent of an action.
26
+
27
+ - **Primary** — High emphasis for main actions like "Save" or "Confirm". Limit to one per screen.
28
+ - **Secondary** — Medium emphasis for multiple actions of equal weight.
29
+ - **Tertiary** — High contrast with inverted background.
30
+ - **Negative** — Destructive actions that can't be undone. Use sparingly.
26
31
 
27
32
  ```jsx
28
- <Button onPress={console.log} variant="secondary">
29
- Secondary
30
- </Button>
33
+ <HStack gap={2} flexWrap="wrap">
34
+ <Button onPress={console.log} variant="primary">
35
+ Primary
36
+ </Button>
37
+ <Button onPress={console.log} variant="secondary">
38
+ Secondary
39
+ </Button>
40
+ <Button onPress={console.log} variant="tertiary">
41
+ Tertiary
42
+ </Button>
43
+ <Button onPress={console.log} variant="negative">
44
+ Negative
45
+ </Button>
46
+ </HStack>
31
47
  ```
32
48
 
33
- ### Tertiary Button
49
+ #### Transparent
34
50
 
35
- These buttons provide high contrast with the background through the use of the themable inverted background color.
51
+ Use transparent buttons for supplementary actions with lower prominence. The container is only visible on interaction. Works with any variant.
36
52
 
37
53
  ```jsx
38
- <Button onPress={console.log} variant="tertiary">
39
- Tertiary
40
- </Button>
54
+ <HStack gap={2}>
55
+ <Button onPress={console.log} transparent>
56
+ Primary
57
+ </Button>
58
+ <Button onPress={console.log} variant="secondary" transparent>
59
+ Secondary
60
+ </Button>
61
+ <Button onPress={console.log} variant="negative" transparent>
62
+ Negative
63
+ </Button>
64
+ </HStack>
41
65
  ```
42
66
 
43
- ### Negative Button
67
+ ### States
68
+
69
+ #### Loading
44
70
 
45
- Negative buttons should be used sparingly for destructive actions that will result in data loss, can’t be undone, or will have significant consequences. They commonly appear in confirmation dialogs as the final confirmation before deleting.
71
+ Use the `loading` prop to indicate an action is in progress. The button becomes non-interactive and displays a spinner while preserving its width.
46
72
 
47
73
  ```jsx
48
- <Button onPress={console.log} variant="negative">
49
- Negative
50
- </Button>
74
+ <HStack gap={2}>
75
+ <Button onPress={console.log} loading>
76
+ Save changes
77
+ </Button>
78
+ <Button onPress={console.log} variant="secondary" loading>
79
+ Submit
80
+ </Button>
81
+ </HStack>
51
82
  ```
52
83
 
53
- ### Transparent Button
84
+ #### Disabled
54
85
 
55
- Transparent buttons are used for less important actions that are supplementary. These buttons have lower prominence since its container is not visible until the button is interacted with. Transparent buttons are frequently used on Cards and can be placed on a variety of backgrounds.
86
+ Use the `disabled` prop to prevent interaction and indicate the action is unavailable.
56
87
 
57
88
  ```jsx
58
89
  <HStack gap={2}>
59
- <Button onPress={console.log} transparent>
90
+ <Button disabled onPress={console.log}>
60
91
  Primary
61
92
  </Button>
62
- <Button onPress={console.log} variant="secondary" transparent>
93
+ <Button disabled onPress={console.log} variant="secondary">
63
94
  Secondary
64
95
  </Button>
65
- <Button onPress={console.log} variant="negative" transparent>
96
+ <Button disabled onPress={console.log} variant="negative">
66
97
  Negative
67
98
  </Button>
68
99
  </HStack>
69
100
  ```
70
101
 
71
- ### Buttons with end icon
102
+ ### Sizing
103
+
104
+ #### Compact
72
105
 
73
- You can add an icon after the label of a button.
106
+ Use `compact` for smaller buttons with reduced padding. Useful in dense UIs or alongside other compact elements.
74
107
 
75
108
  ```jsx
76
- <HStack gap={2}>
77
- <Button onPress={console.log} endIcon="add" endIconActive variant="secondary" compact>
78
- Select file
109
+ <HStack gap={2} alignItems="center">
110
+ <Button onPress={console.log} compact>
111
+ Compact
112
+ </Button>
113
+ <Button onPress={console.log}>Default</Button>
114
+ </HStack>
115
+ ```
116
+
117
+ #### Block
118
+
119
+ Use `block` to make the button expand to fill its container width.
120
+
121
+ ```jsx
122
+ <VStack gap={2}>
123
+ <Button onPress={console.log} block>
124
+ Full width button
125
+ </Button>
126
+ <Button onPress={console.log} variant="secondary" block>
127
+ Another full width
79
128
  </Button>
129
+ </VStack>
130
+ ```
131
+
132
+ ### Icons
133
+
134
+ #### End Icon
135
+
136
+ Add an icon after the label to provide additional context or indicate direction.
137
+
138
+ ```jsx
139
+ <HStack gap={2}>
80
140
  <Button onPress={console.log} endIcon="forwardArrow" variant="secondary" compact>
81
141
  See more
82
142
  </Button>
143
+ <Button onPress={console.log} endIcon="externalLink" variant="secondary" compact>
144
+ Open link
145
+ </Button>
146
+ </HStack>
147
+ ```
148
+
149
+ #### Start Icon
150
+
151
+ Add an icon before the label to reinforce the action.
152
+
153
+ ```jsx
154
+ <HStack gap={2}>
155
+ <Button onPress={console.log} startIcon="add" startIconActive variant="secondary" compact>
156
+ Add item
157
+ </Button>
158
+ <Button onPress={console.log} startIcon="download" variant="secondary" compact>
159
+ Download
160
+ </Button>
161
+ </HStack>
162
+ ```
163
+
164
+ #### Full Width with Icons
165
+
166
+ When using `block` with icons, the content automatically spreads across the button width.
167
+
168
+ ```jsx
169
+ <Button onPress={console.log} startIcon="wallet" endIcon="forwardArrow" variant="secondary" block>
170
+ Connect wallet
171
+ </Button>
172
+ ```
173
+
174
+ ### Accessibility
175
+
176
+ Buttons automatically use their `children` as the accessible label. For buttons with only icons or ambiguous labels, provide an `accessibilityLabel`.
177
+
178
+ ```jsx
179
+ <Button onPress={handleClose} accessibilityLabel="Close dialog">
180
+ ×
181
+ </Button>
182
+ ```
183
+
184
+ ### Composed Examples
185
+
186
+ #### Confirmation Dialog
187
+
188
+ A common pattern using primary and secondary buttons together.
189
+
190
+ ```jsx
191
+ <HStack gap={2} justifyContent="flex-end">
192
+ <Button onPress={console.log} variant="secondary" transparent>
193
+ Cancel
194
+ </Button>
195
+ <Button onPress={console.log}>Confirm</Button>
196
+ </HStack>
197
+ ```
198
+
199
+ #### Destructive Confirmation
200
+
201
+ Use negative buttons with a secondary cancel option for destructive actions.
202
+
203
+ ```jsx
204
+ <HStack gap={2} justifyContent="flex-end">
205
+ <Button onPress={console.log} variant="secondary" transparent>
206
+ Cancel
207
+ </Button>
208
+ <Button onPress={console.log} variant="negative">
209
+ Delete
210
+ </Button>
83
211
  </HStack>
84
212
  ```
85
213
 
214
+ #### Form Actions
215
+
216
+ A full-width primary action with a compact secondary option.
217
+
218
+ ```jsx
219
+ <VStack gap={2}>
220
+ <Button onPress={console.log} block>
221
+ Create account
222
+ </Button>
223
+ <Button onPress={console.log} variant="secondary" transparent block>
224
+ Already have an account? Sign in
225
+ </Button>
226
+ </VStack>
227
+ ```
228
+
86
229
  ## Props
87
230
 
88
231
  | Prop | Type | Required | Default | Description |
@@ -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
@@ -10,82 +10,236 @@ import { Button } from '@coinbase/cds-web/buttons/Button'
10
10
 
11
11
  ## Examples
12
12
 
13
- ### Primary Button
13
+ Buttons allow users to take actions and make choices with a single tap. They communicate what action will occur when the user interacts with them.
14
14
 
15
- Use primary buttons for high emphasis actions. These buttons have the most visual impact and should be reserved for the most important, final actions that complete a flow, like Save, Join now, or Confirm. Try to use one per screen. Multiple primary buttons make it confusing for the user to understand what action they should take.
15
+ ### Basics
16
+
17
+ The only required prop is `children`, which is the button's label. Buttons default to the `primary` variant.
16
18
 
17
19
  ```jsx live
18
- <Button onClick={console.log} variant="primary">
19
- Primary
20
- </Button>
20
+ <Button onClick={console.log}>Get started</Button>
21
21
  ```
22
22
 
23
- ### Secondary Button
23
+ ### Variants
24
+
25
+ Use variants to communicate the importance and intent of an action.
24
26
 
25
- These buttons have a medium level of emphasis that should be used for non-critical actions. Secondary buttons can be used on pages without restrictions and works well for multiple actions of equal weight. They can be used in conjunction with a Primary Button or independently.
27
+ - **Primary** High emphasis for main actions like "Save" or "Confirm". Limit to one per screen.
28
+ - **Secondary** — Medium emphasis for multiple actions of equal weight.
29
+ - **Tertiary** — High contrast with inverted background.
30
+ - **Negative** — Destructive actions that can't be undone. Use sparingly.
26
31
 
27
32
  ```jsx live
28
- <Button onClick={console.log} variant="secondary">
29
- Secondary
30
- </Button>
33
+ <HStack gap={2} flexWrap="wrap">
34
+ <Button onClick={console.log} variant="primary">
35
+ Primary
36
+ </Button>
37
+ <Button onClick={console.log} variant="secondary">
38
+ Secondary
39
+ </Button>
40
+ <Button onClick={console.log} variant="tertiary">
41
+ Tertiary
42
+ </Button>
43
+ <Button onClick={console.log} variant="negative">
44
+ Negative
45
+ </Button>
46
+ </HStack>
31
47
  ```
32
48
 
33
- ### Tertiary Button
49
+ #### Transparent
34
50
 
35
- These buttons provide high contrast with the background through the use of the themable inverted background color.
51
+ Use transparent buttons for supplementary actions with lower prominence. The container is only visible on interaction. Works with any variant.
36
52
 
37
53
  ```jsx live
38
- <Button onClick={console.log} variant="tertiary">
39
- Tertiary
40
- </Button>
54
+ <HStack gap={2} flexWrap="wrap">
55
+ <Button onClick={console.log} transparent>
56
+ Primary
57
+ </Button>
58
+ <Button onClick={console.log} variant="secondary" transparent>
59
+ Secondary
60
+ </Button>
61
+ <Button onClick={console.log} variant="tertiary" transparent>
62
+ Tertiary
63
+ </Button>
64
+ <Button onClick={console.log} variant="negative" transparent>
65
+ Negative
66
+ </Button>
67
+ </HStack>
41
68
  ```
42
69
 
43
- ### Negative Button
70
+ ### States
71
+
72
+ #### Loading
44
73
 
45
- Negative buttons should be used sparingly for destructive actions that will result in data loss, can’t be undone, or will have significant consequences. They commonly appear in confirmation dialogs as the final confirmation before deleting.
74
+ Use the `loading` prop to indicate an action is in progress. The button becomes non-interactive and displays a spinner while preserving its width.
46
75
 
47
76
  ```jsx live
48
- <Button onClick={console.log} variant="negative">
49
- Negative
50
- </Button>
77
+ function LoadingExample() {
78
+ const [isLoading, setIsLoading] = useState(false);
79
+
80
+ const handleClick = () => {
81
+ setIsLoading(true);
82
+ setTimeout(() => setIsLoading(false), 2000);
83
+ };
84
+
85
+ return (
86
+ <HStack gap={2} flexWrap="wrap">
87
+ <Button onClick={handleClick} loading={isLoading}>
88
+ Save changes
89
+ </Button>
90
+ <Button onClick={handleClick} variant="secondary" loading={isLoading}>
91
+ Submit
92
+ </Button>
93
+ </HStack>
94
+ );
95
+ }
51
96
  ```
52
97
 
53
- ### Transparent Button
98
+ #### Disabled
54
99
 
55
- Transparent buttons are used for less important actions that are supplementary. These buttons have lower prominence since its container is not visible until the button is interacted with. Transparent buttons are frequently used on Cards and can be placed on a variety of backgrounds.
100
+ Use the `disabled` prop to prevent interaction and indicate the action is unavailable.
56
101
 
57
102
  ```jsx live
58
- <HStack gap={2}>
59
- <Button onClick={console.log} transparent>
103
+ <HStack gap={2} flexWrap="wrap">
104
+ <Button disabled onClick={console.log}>
60
105
  Primary
61
106
  </Button>
62
- <Button onClick={console.log} variant="secondary" transparent>
63
- Secondary
64
- </Button>
65
- <Button onClick={console.log} variant="tertiary" transparent>
107
+ <Button disabled onClick={console.log} variant="secondary">
66
108
  Secondary
67
109
  </Button>
68
- <Button onClick={console.log} variant="negative" transparent>
110
+ <Button disabled onClick={console.log} variant="negative">
69
111
  Negative
70
112
  </Button>
71
113
  </HStack>
72
114
  ```
73
115
 
74
- ### Buttons with end icon
116
+ ### Sizing
117
+
118
+ #### Compact
119
+
120
+ Use `compact` for smaller buttons with reduced padding. Useful in dense UIs or alongside other compact elements.
121
+
122
+ ```jsx live
123
+ <HStack gap={2} flexWrap="wrap" alignItems="center">
124
+ <Button onClick={console.log} compact>
125
+ Compact
126
+ </Button>
127
+ <Button onClick={console.log}>Default</Button>
128
+ </HStack>
129
+ ```
130
+
131
+ #### Block
75
132
 
76
- You can add an icon after the label of a button.
133
+ Use `block` to make the button expand to fill its container width.
77
134
 
78
135
  ```jsx live
79
- <HStack gap={2}>
80
- <Button onClick={console.log} endIcon="add" endIconActive variant="secondary" compact>
81
- Select file
136
+ <VStack gap={2}>
137
+ <Button onClick={console.log} block>
138
+ Full width button
139
+ </Button>
140
+ <Button onClick={console.log} variant="secondary" block>
141
+ Another full width
82
142
  </Button>
143
+ </VStack>
144
+ ```
145
+
146
+ ### Icons
147
+
148
+ #### End Icon
149
+
150
+ Add an icon after the label to provide additional context or indicate direction.
151
+
152
+ ```jsx live
153
+ <HStack gap={2} flexWrap="wrap">
83
154
  <Button onClick={console.log} endIcon="forwardArrow" variant="secondary" compact>
84
155
  See more
85
156
  </Button>
157
+ <Button onClick={console.log} endIcon="externalLink" variant="secondary" compact>
158
+ Open link
159
+ </Button>
160
+ </HStack>
161
+ ```
162
+
163
+ #### Start Icon
164
+
165
+ Add an icon before the label to reinforce the action.
166
+
167
+ ```jsx live
168
+ <HStack gap={2} flexWrap="wrap">
169
+ <Button onClick={console.log} startIcon="add" startIconActive variant="secondary" compact>
170
+ Add item
171
+ </Button>
172
+ <Button onClick={console.log} startIcon="download" variant="secondary" compact>
173
+ Download
174
+ </Button>
86
175
  </HStack>
87
176
  ```
88
177
 
178
+ #### Full Width with Icons
179
+
180
+ When using `block` with icons, the content automatically spreads across the button width.
181
+
182
+ ```jsx live
183
+ <Button onClick={console.log} startIcon="wallet" endIcon="forwardArrow" variant="secondary" block>
184
+ Connect wallet
185
+ </Button>
186
+ ```
187
+
188
+ ### Accessibility
189
+
190
+ Buttons automatically use their `children` as the accessible label. For buttons with only icons or ambiguous labels, provide an `accessibilityLabel`.
191
+
192
+ ```jsx
193
+ <Button onClick={handleClose} accessibilityLabel="Close dialog">
194
+ ×
195
+ </Button>
196
+ ```
197
+
198
+ ### Composed Examples
199
+
200
+ #### Confirmation Dialog
201
+
202
+ A common pattern using primary and secondary buttons together.
203
+
204
+ ```jsx live
205
+ <HStack gap={2} flexWrap="wrap" justifyContent="flex-end">
206
+ <Button onClick={console.log} variant="secondary" transparent>
207
+ Cancel
208
+ </Button>
209
+ <Button onClick={console.log}>Confirm</Button>
210
+ </HStack>
211
+ ```
212
+
213
+ #### Destructive Confirmation
214
+
215
+ Use negative buttons with a secondary cancel option for destructive actions.
216
+
217
+ ```jsx live
218
+ <HStack gap={2} flexWrap="wrap" justifyContent="flex-end">
219
+ <Button onClick={console.log} variant="secondary" transparent>
220
+ Cancel
221
+ </Button>
222
+ <Button onClick={console.log} variant="negative">
223
+ Delete
224
+ </Button>
225
+ </HStack>
226
+ ```
227
+
228
+ #### Form Actions
229
+
230
+ A full-width primary action with a compact secondary option.
231
+
232
+ ```jsx live
233
+ <VStack gap={2}>
234
+ <Button onClick={console.log} block>
235
+ Create account
236
+ </Button>
237
+ <Button onClick={console.log} variant="secondary" transparent block>
238
+ Already have an account? Sign in
239
+ </Button>
240
+ </VStack>
241
+ ```
242
+
89
243
  ## Props
90
244
 
91
245
  | Prop | Type | Required | Default | Description |
@@ -10,204 +10,99 @@ import { IconButton } from '@coinbase/cds-web/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.
18
-
19
- <br />
20
-
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)).
24
-
25
- :::
17
+ The only required props are `name` (which determines the icon) and `accessibilityLabel` (for screen readers).
26
18
 
27
19
  ```jsx live
28
- <VStack gap={4}>
29
- <VStack gap={2}>
30
- <Text font="title3">Basic variants</Text>
31
- <HStack gap={2}>
32
- <IconButton
33
- active
34
- name="orderHistory"
35
- accessibilityLabel="View transaction history"
36
- variant="primary"
37
- onClick={console.log}
38
- />
39
- <IconButton
40
- active
41
- name="gear"
42
- accessibilityLabel="View settings"
43
- variant="secondary"
44
- onClick={console.log}
45
- />
46
- <IconButton
47
- name="phone"
48
- accessibilityLabel="View settings"
49
- variant="tertiary"
50
- onClick={console.log}
51
- />
52
- <IconButton
53
- name="checkmark"
54
- accessibilityLabel="Approve transaction"
55
- variant="foregroundMuted"
56
- onClick={console.log}
57
- />
58
- </HStack>
59
- </VStack>
20
+ <HStack gap={2} flexWrap="wrap">
21
+ <IconButton name="gear" accessibilityLabel="Open settings" onClick={console.log} />
22
+ <IconButton name="close" accessibilityLabel="Close modal" onClick={console.log} />
23
+ <IconButton name="refresh" accessibilityLabel="Refresh data" onClick={console.log} />
24
+ </HStack>
25
+ ```
60
26
 
61
- <VStack gap={2}>
62
- <Text font="title3">Transparent variants</Text>
63
- <HStack gap={2}>
64
- <IconButton
65
- active
66
- name="orderHistory"
67
- accessibilityLabel="View past order history"
68
- variant="primary"
69
- transparent
70
- onClick={console.log}
71
- />
72
- <IconButton
73
- name="phone"
74
- accessibilityLabel="View settings"
75
- variant="tertiary"
76
- transparent
77
- onClick={console.log}
78
- />
79
- <IconButton
80
- active
81
- name="gear"
82
- accessibilityLabel="Update settings"
83
- variant="secondary"
84
- transparent
85
- onClick={console.log}
86
- />
87
- <IconButton
88
- name="checkmark"
89
- accessibilityLabel="Verify your identity"
90
- variant="foregroundMuted"
91
- transparent
92
- onClick={console.log}
93
- />
94
- </HStack>
95
- </VStack>
27
+ ### Variants
96
28
 
97
- <VStack gap={2}>
98
- <Text font="title3">Loading states</Text>
99
- <HStack gap={2}>
100
- <IconButton
101
- active
102
- name="orderHistory"
103
- accessibilityLabel="Loading transaction history"
104
- variant="primary"
105
- loading
106
- onClick={console.log}
107
- />
108
- <IconButton
109
- active
110
- name="gear"
111
- accessibilityLabel="Loading settings"
112
- variant="secondary"
113
- loading
114
- onClick={console.log}
115
- />
116
- <IconButton
117
- name="checkmark"
118
- accessibilityLabel="Processing approval"
119
- variant="foregroundMuted"
120
- loading
121
- onClick={console.log}
122
- />
123
- </HStack>
124
- </VStack>
125
-
126
- <VStack gap={2}>
127
- <Text font="title3">Disabled states</Text>
128
- <HStack gap={2}>
129
- <IconButton
130
- active
131
- name="orderHistory"
132
- accessibilityLabel="View transaction history"
133
- variant="primary"
134
- disabled
135
- onClick={console.log}
136
- />
137
- <IconButton
138
- active
139
- name="gear"
140
- accessibilityLabel="View settings"
141
- variant="secondary"
142
- disabled
143
- onClick={console.log}
144
- />
145
- <IconButton
146
- name="checkmark"
147
- accessibilityLabel="Approve transaction"
148
- variant="foregroundMuted"
149
- disabled
150
- onClick={console.log}
151
- />
152
- </HStack>
153
- </VStack>
29
+ Use variants to denote intent and importance. The `active` prop fills the icon when enabled.
154
30
 
155
- <VStack gap={2}>
156
- <Text font="title3">Sizing</Text>
157
- <HStack gap={2} alignItems="center">
158
- <IconButton
159
- active
160
- name="gear"
161
- accessibilityLabel="Settings - compact"
162
- variant="primary"
163
- compact
164
- onClick={console.log}
165
- />
166
- <IconButton
167
- active
168
- name="gear"
169
- accessibilityLabel="Settings - regular"
170
- variant="primary"
171
- compact={false}
172
- onClick={console.log}
173
- />
174
- </HStack>
175
- </VStack>
176
- </VStack>
31
+ ```jsx live
32
+ <HStack gap={2} flexWrap="wrap">
33
+ <IconButton
34
+ active
35
+ name="orderHistory"
36
+ accessibilityLabel="View transaction history"
37
+ variant="primary"
38
+ onClick={console.log}
39
+ />
40
+ <IconButton
41
+ active
42
+ name="gear"
43
+ accessibilityLabel="View settings"
44
+ variant="secondary"
45
+ onClick={console.log}
46
+ />
47
+ <IconButton
48
+ name="phone"
49
+ accessibilityLabel="Call support"
50
+ variant="tertiary"
51
+ onClick={console.log}
52
+ />
53
+ <IconButton
54
+ name="checkmark"
55
+ accessibilityLabel="Approve transaction"
56
+ variant="foregroundMuted"
57
+ onClick={console.log}
58
+ />
59
+ </HStack>
177
60
  ```
178
61
 
179
- ### Composed example
62
+ #### Transparent
180
63
 
181
- As referenced above, if you're building a composed system, use the `accessibilityLabelledBy` prop and an `id` on the text node.
64
+ Use the `transparent` prop to remove the background until the user interacts with the button.
182
65
 
183
66
  ```jsx live
184
- function composedExample() {
185
- const [active, setActive] = useState(false);
186
- const name = useMemo(() => (active ? 'dropsActive' : 'dropsInactive'), [active]);
187
- const variant = useMemo(() => (active ? 'primary' : 'foregroundMuted'), [active]);
188
- const label = useMemo(() => (active ? 'Reject drop' : 'Claim drop'), [active]);
189
-
190
- return (
191
- <HStack gap={2} alignItems="center">
192
- <IconButton
193
- name={name}
194
- variant={variant}
195
- onClick={() => setActive((active) => !active)}
196
- // Accessibility props
197
- id="my-icon--id"
198
- accessibilityLabelledBy="my-label--id"
199
- />
200
- <Text font="label1" as="label" htmlFor="my-icon--id" id="my-label--id">
201
- {label}
202
- </Text>
203
- </HStack>
204
- );
205
- }
67
+ <HStack gap={2} flexWrap="wrap">
68
+ <IconButton
69
+ active
70
+ name="orderHistory"
71
+ accessibilityLabel="View past order history"
72
+ variant="primary"
73
+ transparent
74
+ onClick={console.log}
75
+ />
76
+ <IconButton
77
+ active
78
+ name="gear"
79
+ accessibilityLabel="Update settings"
80
+ variant="secondary"
81
+ transparent
82
+ onClick={console.log}
83
+ />
84
+ <IconButton
85
+ name="phone"
86
+ accessibilityLabel="Call support"
87
+ variant="tertiary"
88
+ transparent
89
+ onClick={console.log}
90
+ />
91
+ <IconButton
92
+ name="checkmark"
93
+ accessibilityLabel="Verify your identity"
94
+ variant="foregroundMuted"
95
+ transparent
96
+ onClick={console.log}
97
+ />
98
+ </HStack>
206
99
  ```
207
100
 
208
- ### Loading state
101
+ ### States
102
+
103
+ #### Loading
209
104
 
210
- Use the `loading` prop to show a spinner when an action is in progress. The button becomes non-interactive and shows a loading spinner instead of the icon.
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.
211
106
 
212
107
  ```jsx live
213
108
  function LoadingExample() {
@@ -215,12 +110,11 @@ function LoadingExample() {
215
110
 
216
111
  const handleSubmit = () => {
217
112
  setIsLoading(true);
218
- // Simulate async operation
219
113
  setTimeout(() => setIsLoading(false), 2000);
220
114
  };
221
115
 
222
116
  return (
223
- <HStack gap={2}>
117
+ <HStack gap={2} flexWrap="wrap">
224
118
  <IconButton
225
119
  name="checkmark"
226
120
  accessibilityLabel={isLoading ? 'Processing submission' : 'Submit form'}
@@ -240,18 +134,51 @@ function LoadingExample() {
240
134
  }
241
135
  ```
242
136
 
137
+ #### Disabled
138
+
139
+ Use the `disabled` prop to prevent interaction and show a disabled visual state.
140
+
141
+ ```jsx live
142
+ <HStack gap={2} flexWrap="wrap">
143
+ <IconButton
144
+ active
145
+ name="orderHistory"
146
+ accessibilityLabel="View transaction history"
147
+ variant="primary"
148
+ disabled
149
+ onClick={console.log}
150
+ />
151
+ <IconButton
152
+ active
153
+ name="gear"
154
+ accessibilityLabel="View settings"
155
+ variant="secondary"
156
+ disabled
157
+ onClick={console.log}
158
+ />
159
+ <IconButton
160
+ name="checkmark"
161
+ accessibilityLabel="Approve transaction"
162
+ variant="foregroundMuted"
163
+ disabled
164
+ onClick={console.log}
165
+ />
166
+ </HStack>
167
+ ```
168
+
243
169
  ### Sizing
244
170
 
245
- IconButtons come in two sizes: compact (default) and regular. Use `compact={false}` for larger touch targets.
171
+ IconButtons are compact by default. Use `compact={false}` for larger touch targets.
246
172
 
247
173
  ```jsx live
248
- <HStack gap={2} alignItems="center">
174
+ <HStack gap={2} flexWrap="wrap" alignItems="center">
249
175
  <IconButton
250
176
  active
251
177
  name="gear"
252
178
  accessibilityLabel="Settings - compact"
253
179
  variant="primary"
254
180
  compact
181
+ onClick={console.log}
255
182
  />
256
183
  <IconButton
257
184
  active
@@ -259,18 +186,66 @@ IconButtons come in two sizes: compact (default) and regular. Use `compact={fals
259
186
  accessibilityLabel="Settings - regular"
260
187
  variant="primary"
261
188
  compact={false}
189
+ onClick={console.log}
262
190
  />
263
191
  </HStack>
264
192
  ```
265
193
 
266
- ### A11y
194
+ ### Accessibility
267
195
 
268
- Since icon buttons have no descriptive text or children, an accessibility label must be provided.
196
+ Since icon buttons have no visible text, an `accessibilityLabel` is required to describe the button's purpose for screen readers.
269
197
 
270
198
  ```jsx
271
199
  <IconButton name="close" accessibilityLabel="Close trade modal" />
272
200
  ```
273
201
 
202
+ 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.
203
+
204
+ ### Composed Examples
205
+
206
+ #### Claim Drop
207
+
208
+ A toggleable icon button with an adjacent label. Uses `accessibilityLabelledBy` to associate the button with its visible label.
209
+
210
+ ```jsx live
211
+ function ClaimDropExample() {
212
+ const [active, setActive] = useState(false);
213
+ const variant = useMemo(() => (active ? 'primary' : 'foregroundMuted'), [active]);
214
+ const label = useMemo(() => (active ? 'Reject drop' : 'Claim drop'), [active]);
215
+
216
+ return (
217
+ <HStack gap={2} alignItems="center">
218
+ <IconButton
219
+ name="drops"
220
+ active={active}
221
+ variant={variant}
222
+ onClick={() => setActive((active) => !active)}
223
+ id="claim-drop-button"
224
+ accessibilityLabelledBy="claim-drop-label"
225
+ />
226
+ <Text font="label1" as="label" htmlFor="claim-drop-button" id="claim-drop-label">
227
+ {label}
228
+ </Text>
229
+ </HStack>
230
+ );
231
+ }
232
+ ```
233
+
234
+ #### Notification Bell
235
+
236
+ An icon button with a badge showing the notification count. Uses `DotCount` to display the number of unread notifications.
237
+
238
+ ```jsx live
239
+ <DotCount count={3} overlap="circular" pin="top-end">
240
+ <IconButton
241
+ name="bell"
242
+ accessibilityLabel="Notifications, 3 unread"
243
+ variant="secondary"
244
+ onClick={console.log}
245
+ />
246
+ </DotCount>
247
+ ```
248
+
274
249
  ## Props
275
250
 
276
251
  | Prop | Type | Required | Default | Description |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coinbase/cds-mcp-server",
3
- "version": "8.28.0",
3
+ "version": "8.28.2",
4
4
  "description": "Coinbase Design System - MCP Server",
5
5
  "repository": {
6
6
  "type": "git",