@moises.ai/design-system 3.11.11 → 3.11.13

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.
@@ -13,6 +13,48 @@ import {
13
13
 
14
14
  import { AlertIcon } from '../../icons/AlertIcon'
15
15
 
16
+ const ICON_SIZE = 20
17
+
18
+ function LabeledIconButton({
19
+ label,
20
+ icon: Icon = HomeIcon,
21
+ iconSize = ICON_SIZE,
22
+ ...buttonProps
23
+ }) {
24
+ return (
25
+ <Flex direction="column" gap="2" align="center">
26
+ <Text size="1">{label}</Text>
27
+ <IconButton {...buttonProps}>
28
+ <Icon width={iconSize} height={iconSize} />
29
+ </IconButton>
30
+ </Flex>
31
+ )
32
+ }
33
+
34
+ function IconButtonRow({ items, icon: Icon = HomeIcon }) {
35
+ return (
36
+ <Flex align="center" justify="center" gap="4" wrap="wrap" mt="4">
37
+ {items.map(({ label, ...props }) => (
38
+ <LabeledIconButton
39
+ key={label}
40
+ label={label}
41
+ icon={Icon}
42
+ {...props}
43
+ />
44
+ ))}
45
+ </Flex>
46
+ )
47
+ }
48
+
49
+ function MatrixSection({ title, children }) {
50
+ return (
51
+ <Box>
52
+ <Heading size="4">{title}</Heading>
53
+ {children}
54
+ </Box>
55
+ )
56
+ }
57
+
16
58
  export default {
17
59
  title: 'Components/IconButton',
18
60
  component: IconButton,
@@ -21,8 +63,13 @@ export default {
21
63
  docs: {
22
64
  description: {
23
65
  component: `
24
- IconButton is a button that displays only an icon. It's built on top of Radix UI's IconButton component and
25
- supports various states such as default, hover, and disabled.
66
+ Icon-only action button built on Radix Themes, with Moises tokens for **neutral**, **error**, and **accent** colors.
67
+
68
+ **Accent** is styled for **ghost**, **solid**, and **soft**. **Surface** is neutral-only in this component.
69
+
70
+ **Accessibility:** pair the icon with an \`aria-label\` (or \`title\`) so screen readers get a clear name. Radix passes the underlying \`<button>\` props through.
71
+
72
+ **Color aliases:** \`gray\` → neutral, \`red\` → error, \`cyan\` / \`mint\` → accent.
26
73
 
27
74
  ## Usage
28
75
 
@@ -31,7 +78,7 @@ import { IconButton } from '@moises.ai/design-system'
31
78
  import { HomeIcon } from '@moises.ai/design-system/icons'
32
79
 
33
80
  const MyComponent = () => (
34
- <IconButton onClick={() => console.log('clicked!')}>
81
+ <IconButton aria-label="Home" onClick={() => {}}>
35
82
  <HomeIcon width={20} height={20} />
36
83
  </IconButton>
37
84
  )
@@ -46,7 +93,7 @@ const MyComponent = () => (
46
93
  control: { type: 'select' },
47
94
  options: ['ghost', 'solid', 'soft', 'surface'],
48
95
  description:
49
- 'The visual style of the button. **Note:** solid variant is not available when color is mint. **Note:** surface and soft variants only support gray color.',
96
+ 'Visual style. Accent supports ghost, solid, and soft. Surface uses neutral (gray) in the underlying Radix API.',
50
97
  table: {
51
98
  type: { summary: 'string' },
52
99
  defaultValue: { summary: 'ghost' },
@@ -54,25 +101,34 @@ const MyComponent = () => (
54
101
  },
55
102
  color: {
56
103
  control: { type: 'select' },
57
- options: ['gray', 'red', 'mint', 'cyan'],
104
+ options: ['neutral', 'error', 'accent'],
58
105
  description:
59
- 'The color scheme of the button **Note:** mint color is not available when variant is solid.',
106
+ 'Semantic color. You may also pass legacy names: gray, red, cyan, mint.',
60
107
  table: {
61
108
  type: { summary: 'string' },
62
- defaultValue: { summary: 'gray' },
109
+ defaultValue: { summary: 'neutral' },
63
110
  },
64
111
  },
65
112
  disabled: {
66
- control: { type: 'boolean' },
113
+ control: 'boolean',
67
114
  description: 'Disables the button',
68
115
  table: {
69
116
  type: { summary: 'boolean' },
70
- defaultValue: { summary: 'false' },
117
+ defaultValue: { summary: false },
118
+ },
119
+ },
120
+ toggleable: {
121
+ control: 'boolean',
122
+ description:
123
+ 'Toggle/pressed styling. Only has an effect when variant is ghost or soft.',
124
+ table: {
125
+ type: { summary: 'boolean' },
126
+ defaultValue: { summary: false },
71
127
  },
72
128
  },
73
129
  onClick: {
74
130
  action: 'clicked',
75
- description: 'Function called when the button is clicked',
131
+ description: 'Called when the button is clicked',
76
132
  table: {
77
133
  type: { summary: 'function' },
78
134
  defaultValue: { summary: 'undefined' },
@@ -80,7 +136,7 @@ const MyComponent = () => (
80
136
  },
81
137
  className: {
82
138
  control: false,
83
- description: 'Additional CSS class names to apply to the button',
139
+ description: 'Additional CSS class names',
84
140
  table: {
85
141
  type: { summary: 'string' },
86
142
  defaultValue: { summary: 'undefined' },
@@ -88,445 +144,346 @@ const MyComponent = () => (
88
144
  },
89
145
  children: {
90
146
  control: false,
91
- description: 'Icon component to be rendered as children **(REQUIRED)**',
147
+ description: 'Icon element (required)',
92
148
  table: {
93
149
  type: { summary: 'React.ReactNode' },
94
- defaultValue: { summary: 'undefined' },
95
150
  },
96
151
  },
97
152
  size: {
98
153
  control: { type: 'select' },
99
154
  options: ['1', '2', '3', '4'],
100
- description: 'The size of the button.',
155
+ description: 'Button size (24px 48px hit target).',
101
156
  table: {
102
157
  type: { summary: 'string' },
103
158
  defaultValue: { summary: '1' },
104
159
  },
105
160
  },
106
161
  highContrast: {
107
- control: { type: 'boolean' },
108
- description: 'Whether to use high contrast styling',
162
+ control: 'boolean',
163
+ description: 'Higher contrast text/icon color where supported',
109
164
  table: {
110
165
  type: { summary: 'boolean' },
111
- defaultValue: { summary: 'false' },
166
+ defaultValue: { summary: false },
112
167
  },
113
168
  },
114
169
  loading: {
115
- control: { type: 'boolean' },
116
- description: 'Shows a loading indicator',
170
+ control: 'boolean',
171
+ description: 'Shows loading state',
117
172
  table: {
118
173
  type: { summary: 'boolean' },
119
- defaultValue: { summary: 'false' },
120
- },
121
- },
122
- iconComponent: {
123
- control: false,
124
- description: 'Internal use only for story examples',
125
- table: {
126
- disable: true,
174
+ defaultValue: { summary: false },
127
175
  },
128
176
  },
129
177
  },
130
- args: {
131
- // Default values for all stories
132
- variant: 'ghost',
133
- color: 'gray',
134
- },
135
178
  }
136
179
 
137
180
  const Template = (args) => (
138
- <IconButton {...args}>
139
- {args.iconComponent ? (
140
- args.iconComponent
141
- ) : (
142
- <HomeIcon width={20} height={20} />
143
- )}
181
+ <IconButton {...args} aria-label="Demo">
182
+ <HomeIcon width={ICON_SIZE} height={ICON_SIZE} />
144
183
  </IconButton>
145
184
  )
146
185
 
147
- const ButtonWithLabel = ({ label, ...props }) => (
148
- <Flex direction="column" gap="2" align="center">
149
- <Text size="1">{label}</Text>
150
- <IconButton {...props}>
151
- <HomeIcon width={20} height={20} />
152
- </IconButton>
153
- </Flex>
154
- )
155
-
156
186
  export const Default = {
157
187
  render: Template,
188
+ args: {
189
+ variant: 'ghost',
190
+ color: 'neutral',
191
+ size: '1',
192
+ disabled: false,
193
+ loading: false,
194
+ highContrast: false,
195
+ toggleable: false,
196
+ },
158
197
  }
159
198
 
160
199
  export const Variants = {
161
- name: 'Button Variants',
200
+ name: 'Overview',
201
+ parameters: {
202
+ layout: 'padded',
203
+ },
162
204
  render: () => (
163
205
  <Flex direction="column" gap="8">
164
- <Box>
165
- <Heading size="4">Available Variants</Heading>
166
- <Grid columns="4" gap="6" mt="4" align="center">
167
- <ButtonWithLabel label="Ghost" variant="ghost" />
168
- <ButtonWithLabel label="Solid" variant="solid" />
169
- <ButtonWithLabel label="Soft" variant="soft" />
170
- <ButtonWithLabel label="Surface" variant="surface" />
206
+ <MatrixSection title="Variants (neutral)">
207
+ <Grid columns={{ initial: '2', sm: '4' }} gap="6" mt="4" align="center">
208
+ <LabeledIconButton label="Ghost" variant="ghost" />
209
+ <LabeledIconButton label="Solid" variant="solid" />
210
+ <LabeledIconButton label="Soft" variant="soft" />
211
+ <LabeledIconButton label="Surface" variant="surface" />
212
+ </Grid>
213
+ </MatrixSection>
214
+
215
+ <MatrixSection title="Semantic colors (ghost)">
216
+ <Grid columns="3" gap="6" mt="4" align="center">
217
+ <LabeledIconButton label="Neutral" color="neutral" />
218
+ <LabeledIconButton label="Error" color="error" />
219
+ <LabeledIconButton label="Accent" color="accent" icon={AlertIcon} />
171
220
  </Grid>
172
- </Box>
221
+ </MatrixSection>
173
222
 
174
- <Box>
175
- <Heading size="4">Available Colors</Heading>
176
- <Grid columns="4" gap="6" mt="4" align="center">
177
- <ButtonWithLabel label="Gray" color="gray" />
178
- <ButtonWithLabel label="Red" color="red" />
179
- <ButtonWithLabel label="Mint" color="mint" />
180
- <ButtonWithLabel label="Cyan" color="cyan" />
223
+ <MatrixSection title="Accent (ghost, solid & soft)">
224
+ <Grid columns="3" gap="6" mt="4" align="center">
225
+ <LabeledIconButton
226
+ label="Ghost"
227
+ variant="ghost"
228
+ color="accent"
229
+ icon={AlertIcon}
230
+ />
231
+ <LabeledIconButton
232
+ label="Solid"
233
+ variant="solid"
234
+ color="accent"
235
+ icon={AlertIcon}
236
+ />
237
+ <LabeledIconButton
238
+ label="Soft"
239
+ variant="soft"
240
+ color="accent"
241
+ icon={AlertIcon}
242
+ />
181
243
  </Grid>
182
- </Box>
244
+ </MatrixSection>
183
245
 
184
- <Box>
185
- <Heading size="4">High Contrast Options</Heading>
246
+ <MatrixSection title="Contrast">
186
247
  <Grid columns="2" gap="6" mt="4" align="center">
187
- <ButtonWithLabel label="Normal Contrast" />
188
- <ButtonWithLabel label="High Contrast" highContrast />
248
+ <LabeledIconButton label="Default" />
249
+ <LabeledIconButton label="High contrast" highContrast />
189
250
  </Grid>
190
- </Box>
251
+ </MatrixSection>
191
252
 
192
- <Box>
193
- <Heading size="4">State Variations</Heading>
253
+ <MatrixSection title="States">
194
254
  <Grid columns="3" gap="6" mt="4" align="center">
195
- <ButtonWithLabel label="Default" />
196
- <ButtonWithLabel label="Disabled" disabled />
197
- <ButtonWithLabel label="Loading" loading />
255
+ <LabeledIconButton label="Default" />
256
+ <LabeledIconButton label="Disabled" disabled />
257
+ <LabeledIconButton label="Loading" loading />
198
258
  </Grid>
199
- </Box>
259
+ </MatrixSection>
200
260
  </Flex>
201
261
  ),
202
262
  }
203
263
 
204
- export const ColorVariants = {
205
- name: 'Complete Color Examples',
264
+ export const Sizes = {
265
+ parameters: {
266
+ layout: 'padded',
267
+ },
206
268
  render: () => (
207
- <Flex direction="column" gap="8">
208
- <Box>
209
- <Heading size="4">Mint Color (only ghost variant)</Heading>
210
- <Flex align="center" justify="center" gap="4" wrap="wrap" mt="4">
211
- <Flex direction="column" gap="2" align="center">
212
- <Text size="1">Ghost default</Text>
213
- <IconButton variant="ghost" color="mint">
214
- <AlertIcon width={20} height={20} />
215
- </IconButton>
216
- </Flex>
217
- <Flex direction="column" gap="2" align="center">
218
- <Text size="1">Ghost highContrast</Text>
219
- <IconButton variant="ghost" color="mint" highContrast>
220
- <AlertIcon width={20} height={20} />
221
- </IconButton>
222
- </Flex>
223
- </Flex>
224
- <Flex align="center" justify="center" gap="4" wrap="wrap" mt="4">
225
- <Flex direction="column" gap="2" align="center">
226
- <Text size="1">Ghost default disabled</Text>
227
- <IconButton variant="ghost" color="mint" disabled>
228
- <AlertIcon width={20} height={20} />
229
- </IconButton>
230
- </Flex>
231
- <Flex direction="column" gap="2" align="center">
232
- <Text size="1">Ghost highContrast disabled</Text>
233
- <IconButton
234
- variant="ghost"
235
- color="mint"
236
- disabled
237
- highContrast={true}
238
- >
239
- <AlertIcon width={20} height={20} />
240
- </IconButton>
241
- </Flex>
242
- </Flex>
243
- <Flex align="center" justify="center" gap="4" wrap="wrap" mt="4">
244
- <Flex direction="column" gap="2" align="center">
245
- <Text size="1">Ghost loading</Text>
246
- <IconButton variant="ghost" color="mint" loading>
247
- <AlertIcon width={20} height={20} />
248
- </IconButton>
249
- </Flex>
250
- <Flex direction="column" gap="2" align="center">
251
- <Text size="1">Ghost loading highContrast</Text>
252
- <IconButton variant="ghost" color="mint" loading highContrast>
253
- <AlertIcon width={20} height={20} />
254
- </IconButton>
255
- </Flex>
256
- </Flex>
257
- </Box>
269
+ <Flex direction="column" gap="4" align="center">
270
+ <Heading size="4">Sizes (ghost, neutral)</Heading>
271
+ <Text size="2" color="gray">
272
+ Size tokens 1–4: 24px, 32px, 40px, 48px touch targets.
273
+ </Text>
274
+ <Flex align="end" justify="center" gap="6" wrap="wrap" mt="4">
275
+ {['1', '2', '3', '4'].map((size) => (
276
+ <LabeledIconButton
277
+ key={size}
278
+ label={`Size ${size}`}
279
+ size={size}
280
+ aria-label={`Size ${size}`}
281
+ />
282
+ ))}
283
+ </Flex>
284
+ </Flex>
285
+ ),
286
+ }
258
287
 
259
- <Box>
260
- <Heading size="4">Gray Color (all variants)</Heading>
261
- <Flex align="center" justify="center" gap="4" wrap="wrap" mt="4">
262
- <Flex direction="column" gap="2" align="center">
263
- <Text size="1">Ghost default</Text>
264
- <IconButton variant="ghost" color="gray">
265
- <AlertIcon width={20} height={20} />
266
- </IconButton>
267
- </Flex>
268
- <Flex direction="column" gap="2" align="center">
269
- <Text size="1">Ghost highContrast</Text>
270
- <IconButton variant="ghost" color="gray" highContrast>
271
- <AlertIcon width={20} height={20} />
272
- </IconButton>
273
- </Flex>
274
- <Flex direction="column" gap="2" align="center">
275
- <Text size="1">Solid default</Text>
276
- <IconButton variant="solid" color="gray">
277
- <AlertIcon width={20} height={20} />
278
- </IconButton>
279
- </Flex>
280
- <Flex direction="column" gap="2" align="center">
281
- <Text size="1">Solid highContrast</Text>
282
- <IconButton variant="solid" color="gray" highContrast>
283
- <AlertIcon width={20} height={20} />
284
- </IconButton>
285
- </Flex>
286
- </Flex>
287
- <Flex align="center" justify="center" gap="4" wrap="wrap" mt="4">
288
- <Flex direction="column" gap="2" align="center">
289
- <Text size="1">Soft default</Text>
290
- <IconButton variant="soft" color="gray">
291
- <AlertIcon width={20} height={20} />
292
- </IconButton>
293
- </Flex>
294
- <Flex direction="column" gap="2" align="center">
295
- <Text size="1">Soft highContrast</Text>
296
- <IconButton variant="soft" color="gray" highContrast>
297
- <AlertIcon width={20} height={20} />
298
- </IconButton>
299
- </Flex>
300
- <Flex direction="column" gap="2" align="center">
301
- <Text size="1">Surface default</Text>
302
- <IconButton variant="surface" color="gray">
303
- <AlertIcon width={20} height={20} />
304
- </IconButton>
305
- </Flex>
306
- <Flex direction="column" gap="2" align="center">
307
- <Text size="1">Surface highContrast</Text>
308
- <IconButton variant="surface" color="gray" highContrast>
309
- <AlertIcon width={20} height={20} />
310
- </IconButton>
311
- </Flex>
312
- </Flex>
313
- <Flex align="center" justify="center" gap="4" wrap="wrap" mt="4">
314
- <Flex direction="column" gap="2" align="center">
315
- <Text size="1">Ghost disabled</Text>
316
- <IconButton variant="ghost" color="gray" disabled>
317
- <HomeIcon width={20} height={20} />
318
- </IconButton>
319
- </Flex>
320
- <Flex direction="column" gap="2" align="center">
321
- <Text size="1">Solid disabled</Text>
322
- <IconButton variant="solid" color="gray" disabled>
323
- <HomeIcon width={20} height={20} />
324
- </IconButton>
325
- </Flex>
326
- <Flex direction="column" gap="2" align="center">
327
- <Text size="1">Soft disabled</Text>
328
- <IconButton variant="soft" color="gray" disabled>
329
- <HomeIcon width={20} height={20} />
330
- </IconButton>
331
- </Flex>
332
- <Flex direction="column" gap="2" align="center">
333
- <Text size="1">Surface disabled</Text>
334
- <IconButton variant="surface" color="gray" disabled>
335
- <HomeIcon width={20} height={20} />
336
- </IconButton>
337
- </Flex>
338
- </Flex>
339
- <Flex align="center" justify="center" gap="4" wrap="wrap" mt="4">
340
- <Flex direction="column" gap="2" align="center">
341
- <Text size="1">Ghost loading</Text>
342
- <IconButton variant="ghost" color="gray" loading>
343
- <HomeIcon width={20} height={20} />
344
- </IconButton>
345
- </Flex>
346
- <Flex direction="column" gap="2" align="center">
347
- <Text size="1">Solid loading</Text>
348
- <IconButton variant="solid" color="gray" loading>
349
- <HomeIcon width={20} height={20} />
350
- </IconButton>
351
- </Flex>
352
- <Flex direction="column" gap="2" align="center">
353
- <Text size="1">Soft loading</Text>
354
- <IconButton variant="soft" color="gray" loading>
355
- <HomeIcon width={20} height={20} />
356
- </IconButton>
357
- </Flex>
358
- <Flex direction="column" gap="2" align="center">
359
- <Text size="1">Surface loading</Text>
360
- <IconButton variant="surface" color="gray" loading>
361
- <HomeIcon width={20} height={20} />
362
- </IconButton>
363
- </Flex>
364
- </Flex>
365
- </Box>
288
+ export const CommonIcons = {
289
+ name: 'Common icons',
290
+ parameters: {
291
+ layout: 'padded',
292
+ },
293
+ render: () => (
294
+ <Flex direction="column" gap="4">
295
+ <Heading size="4">Same button, different icons</Heading>
296
+ <Text size="2" color="gray">
297
+ Each example sets <Text weight="bold">aria-label</Text> for accessibility.
298
+ </Text>
299
+ <Flex align="center" justify="center" gap="4" wrap="wrap" mt="4">
300
+ {[
301
+ { Icon: HomeIcon, label: 'Home' },
302
+ { Icon: MagnifyingGlassIcon, label: 'Search' },
303
+ { Icon: PlusIcon, label: 'Add' },
304
+ { Icon: Cross1Icon, label: 'Close' },
305
+ { Icon: ChevronRightIcon, label: 'Next' },
306
+ { Icon: DownloadIcon, label: 'Download' },
307
+ { Icon: TrashIcon, label: 'Delete' },
308
+ { Icon: HeartIcon, label: 'Favorite' },
309
+ ].map(({ Icon, label }) => (
310
+ <IconButton
311
+ key={label}
312
+ variant="ghost"
313
+ color="neutral"
314
+ aria-label={label}
315
+ >
316
+ <Icon width={ICON_SIZE} height={ICON_SIZE} />
317
+ </IconButton>
318
+ ))}
319
+ </Flex>
320
+ </Flex>
321
+ ),
322
+ }
323
+
324
+ const ACCENT_MATRIX = [
325
+ [
326
+ { label: 'Ghost default', variant: 'ghost', color: 'accent' },
327
+ { label: 'Ghost highContrast', variant: 'ghost', color: 'accent', highContrast: true },
328
+ { label: 'Solid default', variant: 'solid', color: 'accent' },
329
+ { label: 'Solid highContrast', variant: 'solid', color: 'accent', highContrast: true },
330
+ { label: 'Soft default', variant: 'soft', color: 'accent' },
331
+ { label: 'Soft highContrast', variant: 'soft', color: 'accent', highContrast: true },
332
+ ],
333
+ [
334
+ { label: 'Ghost disabled', variant: 'ghost', color: 'accent', disabled: true },
335
+ {
336
+ label: 'Ghost highContrast disabled',
337
+ variant: 'ghost',
338
+ color: 'accent',
339
+ disabled: true,
340
+ highContrast: true,
341
+ },
342
+ { label: 'Solid disabled', variant: 'solid', color: 'accent', disabled: true },
343
+ {
344
+ label: 'Solid highContrast disabled',
345
+ variant: 'solid',
346
+ color: 'accent',
347
+ disabled: true,
348
+ highContrast: true,
349
+ },
350
+ { label: 'Soft disabled', variant: 'soft', color: 'accent', disabled: true },
351
+ {
352
+ label: 'Soft highContrast disabled',
353
+ variant: 'soft',
354
+ color: 'accent',
355
+ disabled: true,
356
+ highContrast: true,
357
+ },
358
+ ],
359
+ [
360
+ { label: 'Ghost loading', variant: 'ghost', color: 'accent', loading: true },
361
+ {
362
+ label: 'Ghost highContrast loading',
363
+ variant: 'ghost',
364
+ color: 'accent',
365
+ loading: true,
366
+ highContrast: true,
367
+ },
368
+ { label: 'Solid loading', variant: 'solid', color: 'accent', loading: true },
369
+ {
370
+ label: 'Solid highContrast loading',
371
+ variant: 'solid',
372
+ color: 'accent',
373
+ loading: true,
374
+ highContrast: true,
375
+ },
376
+ { label: 'Soft loading', variant: 'soft', color: 'accent', loading: true },
377
+ {
378
+ label: 'Soft highContrast loading',
379
+ variant: 'soft',
380
+ color: 'accent',
381
+ loading: true,
382
+ highContrast: true,
383
+ },
384
+ ],
385
+ ]
386
+
387
+ const NEUTRAL_MATRIX = [
388
+ [
389
+ { label: 'Ghost default', variant: 'ghost', color: 'neutral' },
390
+ { label: 'Ghost highContrast', variant: 'ghost', color: 'neutral', highContrast: true },
391
+ { label: 'Solid default', variant: 'solid', color: 'neutral' },
392
+ { label: 'Solid highContrast', variant: 'solid', color: 'neutral', highContrast: true },
393
+ ],
394
+ [
395
+ { label: 'Soft default', variant: 'soft', color: 'neutral' },
396
+ { label: 'Soft highContrast', variant: 'soft', color: 'neutral', highContrast: true },
397
+ { label: 'Surface default', variant: 'surface', color: 'neutral' },
398
+ { label: 'Surface highContrast', variant: 'surface', color: 'neutral', highContrast: true },
399
+ ],
400
+ [
401
+ { label: 'Ghost disabled', variant: 'ghost', color: 'neutral', disabled: true },
402
+ { label: 'Solid disabled', variant: 'solid', color: 'neutral', disabled: true },
403
+ { label: 'Soft disabled', variant: 'soft', color: 'neutral', disabled: true },
404
+ { label: 'Surface disabled', variant: 'surface', color: 'neutral', disabled: true },
405
+ ],
406
+ [
407
+ { label: 'Ghost loading', variant: 'ghost', color: 'neutral', loading: true },
408
+ { label: 'Solid loading', variant: 'solid', color: 'neutral', loading: true },
409
+ { label: 'Soft loading', variant: 'soft', color: 'neutral', loading: true },
410
+ { label: 'Surface loading', variant: 'surface', color: 'neutral', loading: true },
411
+ ],
412
+ ]
413
+
414
+ const ERROR_MATRIX = [
415
+ [
416
+ { label: 'Ghost default', variant: 'ghost', color: 'error' },
417
+ { label: 'Ghost highContrast', variant: 'ghost', color: 'error', highContrast: true },
418
+ { label: 'Solid default', variant: 'solid', color: 'error' },
419
+ { label: 'Solid highContrast', variant: 'solid', color: 'error', highContrast: true },
420
+ ],
421
+ [
422
+ { label: 'Ghost disabled', variant: 'ghost', color: 'error', disabled: true },
423
+ {
424
+ label: 'Ghost highContrast disabled',
425
+ variant: 'ghost',
426
+ color: 'error',
427
+ disabled: true,
428
+ highContrast: true,
429
+ },
430
+ { label: 'Solid disabled', variant: 'solid', color: 'error', disabled: true },
431
+ {
432
+ label: 'Solid highContrast disabled',
433
+ variant: 'solid',
434
+ color: 'error',
435
+ disabled: true,
436
+ highContrast: true,
437
+ },
438
+ ],
439
+ [
440
+ { label: 'Ghost loading', variant: 'ghost', color: 'error', loading: true },
441
+ {
442
+ label: 'Ghost highContrast loading',
443
+ variant: 'ghost',
444
+ color: 'error',
445
+ loading: true,
446
+ highContrast: true,
447
+ },
448
+ { label: 'Solid loading', variant: 'solid', color: 'error', loading: true },
449
+ {
450
+ label: 'Solid highContrast loading',
451
+ variant: 'solid',
452
+ color: 'error',
453
+ loading: true,
454
+ highContrast: true,
455
+ },
456
+ ],
457
+ ]
458
+
459
+ export const ColorMatrix = {
460
+ name: 'Color matrix',
461
+ parameters: {
462
+ layout: 'padded',
463
+ },
464
+ render: () => (
465
+ <Flex direction="column" gap="8">
466
+ <MatrixSection title="Accent (ghost, solid & soft)">
467
+ {ACCENT_MATRIX.map((row, i) => (
468
+ <IconButtonRow key={i} items={row} icon={AlertIcon} />
469
+ ))}
470
+ </MatrixSection>
366
471
 
367
- <Box>
368
- <Heading size="4">Red Color (ghost and solid variants)</Heading>
369
- <Flex align="center" justify="center" gap="4" wrap="wrap" mt="4">
370
- <Flex direction="column" gap="2" align="center">
371
- <Text size="1">Ghost default</Text>
372
- <IconButton variant="ghost" color="red">
373
- <HomeIcon width={20} height={20} />
374
- </IconButton>
375
- </Flex>
376
- <Flex direction="column" gap="2" align="center">
377
- <Text size="1">Ghost highContrast</Text>
378
- <IconButton variant="ghost" color="red" highContrast>
379
- <HomeIcon width={20} height={20} />
380
- </IconButton>
381
- </Flex>
382
- <Flex direction="column" gap="2" align="center">
383
- <Text size="1">Solid default</Text>
384
- <IconButton variant="solid" color="red">
385
- <HomeIcon width={20} height={20} />
386
- </IconButton>
387
- </Flex>
388
- <Flex direction="column" gap="2" align="center">
389
- <Text size="1">Solid highContrast</Text>
390
- <IconButton variant="solid" color="red" highContrast>
391
- <HomeIcon width={20} height={20} />
392
- </IconButton>
393
- </Flex>
394
- </Flex>
395
- <Flex align="center" justify="center" gap="4" wrap="wrap" mt="4">
396
- <Flex direction="column" gap="2" align="center">
397
- <Text size="1">Ghost disabled</Text>
398
- <IconButton variant="ghost" color="red" disabled>
399
- <HomeIcon width={20} height={20} />
400
- </IconButton>
401
- </Flex>
402
- <Flex direction="column" gap="2" align="center">
403
- <Text size="1">Ghost highContrast disabled</Text>
404
- <IconButton variant="ghost" color="red" disabled highContrast>
405
- <HomeIcon width={20} height={20} />
406
- </IconButton>
407
- </Flex>
408
- <Flex direction="column" gap="2" align="center">
409
- <Text size="1">Solid disabled</Text>
410
- <IconButton variant="solid" color="red" disabled>
411
- <HomeIcon width={20} height={20} />
412
- </IconButton>
413
- </Flex>
414
- <Flex direction="column" gap="2" align="center">
415
- <Text size="1">Solid highContrast disabled</Text>
416
- <IconButton variant="solid" color="red" disabled highContrast>
417
- <HomeIcon width={20} height={20} />
418
- </IconButton>
419
- </Flex>
420
- </Flex>
421
- <Flex align="center" justify="center" gap="4" wrap="wrap" mt="4">
422
- <Flex direction="column" gap="2" align="center">
423
- <Text size="1">Ghost loading</Text>
424
- <IconButton variant="ghost" color="red" loading>
425
- <HomeIcon width={20} height={20} />
426
- </IconButton>
427
- </Flex>
428
- <Flex direction="column" gap="2" align="center">
429
- <Text size="1">Ghost highContrast loading</Text>
430
- <IconButton variant="ghost" color="red" loading highContrast>
431
- <HomeIcon width={20} height={20} />
432
- </IconButton>
433
- </Flex>
434
- <Flex direction="column" gap="2" align="center">
435
- <Text size="1">Solid loading</Text>
436
- <IconButton variant="solid" color="red" loading>
437
- <HomeIcon width={20} height={20} />
438
- </IconButton>
439
- </Flex>
440
- <Flex direction="column" gap="2" align="center">
441
- <Text size="1">Solid highContrast loading</Text>
442
- <IconButton variant="solid" color="red" loading highContrast>
443
- <HomeIcon width={20} height={20} />
444
- </IconButton>
445
- </Flex>
446
- </Flex>
447
- </Box>
472
+ <MatrixSection title="Neutral (all variants)">
473
+ {NEUTRAL_MATRIX.map((row, i) => (
474
+ <IconButtonRow
475
+ key={i}
476
+ items={row}
477
+ icon={i === 2 || i === 3 ? HomeIcon : AlertIcon}
478
+ />
479
+ ))}
480
+ </MatrixSection>
448
481
 
449
- <Box>
450
- <Heading size="4">Cyan Color (ghost and solid variants)</Heading>
451
- <Flex align="center" justify="center" gap="4" wrap="wrap" mt="4">
452
- <Flex direction="column" gap="2" align="center">
453
- <Text size="1">Ghost default</Text>
454
- <IconButton variant="ghost" color="cyan">
455
- <HomeIcon width={20} height={20} />
456
- </IconButton>
457
- </Flex>
458
- <Flex direction="column" gap="2" align="center">
459
- <Text size="1">Ghost highContrast</Text>
460
- <IconButton variant="ghost" color="cyan" highContrast>
461
- <HomeIcon width={20} height={20} />
462
- </IconButton>
463
- </Flex>
464
- <Flex direction="column" gap="2" align="center">
465
- <Text size="1">Solid default</Text>
466
- <IconButton variant="solid" color="cyan">
467
- <HomeIcon width={20} height={20} />
468
- </IconButton>
469
- </Flex>
470
- <Flex direction="column" gap="2" align="center">
471
- <Text size="1">Solid highContrast</Text>
472
- <IconButton variant="solid" color="cyan" highContrast>
473
- <HomeIcon width={20} height={20} />
474
- </IconButton>
475
- </Flex>
476
- </Flex>
477
- <Flex align="center" justify="center" gap="4" wrap="wrap" mt="4">
478
- <Flex direction="column" gap="2" align="center">
479
- <Text size="1">Ghost disabled</Text>
480
- <IconButton variant="ghost" color="cyan" disabled>
481
- <HomeIcon width={20} height={20} />
482
- </IconButton>
483
- </Flex>
484
- <Flex direction="column" gap="2" align="center">
485
- <Text size="1">Ghost highContrast disabled</Text>
486
- <IconButton variant="ghost" color="cyan" disabled highContrast>
487
- <HomeIcon width={20} height={20} />
488
- </IconButton>
489
- </Flex>
490
- <Flex direction="column" gap="2" align="center">
491
- <Text size="1">Solid disabled</Text>
492
- <IconButton variant="solid" color="cyan" disabled>
493
- <HomeIcon width={20} height={20} />
494
- </IconButton>
495
- </Flex>
496
- <Flex direction="column" gap="2" align="center">
497
- <Text size="1">Solid highContrast disabled</Text>
498
- <IconButton variant="solid" color="cyan" disabled highContrast>
499
- <HomeIcon width={20} height={20} />
500
- </IconButton>
501
- </Flex>
502
- </Flex>
503
- <Flex align="center" justify="center" gap="4" wrap="wrap" mt="4">
504
- <Flex direction="column" gap="2" align="center">
505
- <Text size="1">Ghost loading</Text>
506
- <IconButton variant="ghost" color="cyan" loading>
507
- <HomeIcon width={20} height={20} />
508
- </IconButton>
509
- </Flex>
510
- <Flex direction="column" gap="2" align="center">
511
- <Text size="1">Ghost highContrast loading</Text>
512
- <IconButton variant="ghost" color="cyan" loading highContrast>
513
- <HomeIcon width={20} height={20} />
514
- </IconButton>
515
- </Flex>
516
- <Flex direction="column" gap="2" align="center">
517
- <Text size="1">Solid loading</Text>
518
- <IconButton variant="solid" color="cyan" loading>
519
- <HomeIcon width={20} height={20} />
520
- </IconButton>
521
- </Flex>
522
- <Flex direction="column" gap="2" align="center">
523
- <Text size="1">Solid highContrast loading</Text>
524
- <IconButton variant="solid" color="cyan" loading highContrast>
525
- <HomeIcon width={20} height={20} />
526
- </IconButton>
527
- </Flex>
528
- </Flex>
529
- </Box>
482
+ <MatrixSection title="Error (ghost and solid)">
483
+ {ERROR_MATRIX.map((row, i) => (
484
+ <IconButtonRow key={i} items={row} />
485
+ ))}
486
+ </MatrixSection>
530
487
  </Flex>
531
488
  ),
532
489
  }