@iress-oss/ids-components 6.0.0-beta.2 → 6.0.0-beta.4
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/.ai/components/tag.md +43 -3
- package/.ai/skills/figma-to-ids.md +136 -61
- package/.ai/skills/ui-translation.md +98 -72
- package/README.md +16 -1
- package/dist/{Autocomplete-JZcorz66.js → Autocomplete-CuUjmIAw.js} +66 -63
- package/dist/Shadow-DdGxqWgh.js +56 -0
- package/dist/components/Autocomplete/Autocomplete.js +1 -1
- package/dist/components/Autocomplete/hooks/useAutocompleteSearch.js +1 -1
- package/dist/components/Autocomplete/index.js +2 -2
- package/dist/components/Icon/helpers/getMaterialSymbolsList.js +1 -1
- package/dist/components/Menu/Menu.js +4 -7
- package/dist/components/Select/Select.js +1 -1
- package/dist/components/Select/components/SelectOptions.js +2 -2
- package/dist/components/Select/index.js +1 -1
- package/dist/components/Slider/components/SliderTicks.js +2 -2
- package/dist/components/Tag/Tag.d.ts +15 -23
- package/dist/components/Tag/Tag.js +28 -31
- package/dist/components/Tag/Tag.styles.d.ts +8 -9
- package/dist/components/Tag/Tag.styles.js +26 -14
- package/dist/index.d-BJM5_ZcV.js +4 -0
- package/dist/main.js +3 -3
- package/dist/patterns/ContextualMenu/ContextualMenu.d.ts +1 -1
- package/dist/patterns/ContextualMenu/ContextualMenu.js +22 -21
- package/dist/patterns/DropdownMenu/DropdownMenu.js +1 -1
- package/dist/patterns/Shadow/Shadow.js +1 -1
- package/dist/patterns/Shadow/index.js +1 -1
- package/dist/style.css +1 -1
- package/dist/{useAutocompleteSearch-Dl1-OeQy.js → useAutocompleteSearch-BJ_hhoKp.js} +3 -3
- package/package.json +10 -10
- package/dist/Shadow-BGGBsmrn.js +0 -56
- package/dist/index.d-Dsa3mJDa.js +0 -4
package/.ai/components/tag.md
CHANGED
|
@@ -63,12 +63,46 @@ Use semantic status values (`danger`, `info`, `success`, `warning`) when tags ne
|
|
|
63
63
|
|
|
64
64
|
[View "Status" example in Storybook →](https://main--691abcc79dfa560a36d0a74f.chromatic.com/?path=/story/components_components-tag--status)
|
|
65
65
|
|
|
66
|
+
### Bordered tags
|
|
67
|
+
|
|
68
|
+
Set `bordered` to render a tag with a visible border using the tag's current
|
|
69
|
+
colour, without altering its background. This enhances visibility and makes tags
|
|
70
|
+
look more interactive — useful for dropdown filter tags or any context where
|
|
71
|
+
tags need to stand out.
|
|
72
|
+
|
|
73
|
+
```tsx
|
|
74
|
+
<IressInline gap="sm">
|
|
75
|
+
<IressTag bordered>
|
|
76
|
+
No mode
|
|
77
|
+
</IressTag>
|
|
78
|
+
{BADGE_MODES.map((mode) => (
|
|
79
|
+
<IressTag key={mode} mode={mode} bordered>
|
|
80
|
+
{mode}
|
|
81
|
+
</IressTag>
|
|
82
|
+
))}
|
|
83
|
+
{STATUSES.map((status) => (
|
|
84
|
+
<IressTag key={status} mode={status} bordered>
|
|
85
|
+
{status}
|
|
86
|
+
</IressTag>
|
|
87
|
+
))}
|
|
88
|
+
</IressInline>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
[View "Bordered" example in Storybook →](https://main--691abcc79dfa560a36d0a74f.chromatic.com/?path=/story/components_components-tag--bordered)
|
|
92
|
+
|
|
66
93
|
### Clickable tags
|
|
67
94
|
|
|
68
|
-
Tags can be made clickable by
|
|
95
|
+
Tags can be made clickable by setting `element="button"`. This is the
|
|
96
|
+
recommended, explicit API and renders the tag as a `<button>` with hover
|
|
97
|
+
styles to indicate it is clickable.
|
|
98
|
+
|
|
99
|
+
For backwards compatibility, passing `onClick` without setting `element` is
|
|
100
|
+
also supported and will automatically render the tag as a `<button>`.
|
|
101
|
+
|
|
102
|
+
Use `element="a"` to render the tag as a link.
|
|
69
103
|
|
|
70
104
|
```tsx
|
|
71
|
-
<IressTag>
|
|
105
|
+
<IressTag bordered>
|
|
72
106
|
Tag
|
|
73
107
|
</IressTag>
|
|
74
108
|
```
|
|
@@ -124,12 +158,18 @@ Query tags by their text content:
|
|
|
124
158
|
const tag = screen.getByText('Category');
|
|
125
159
|
```
|
|
126
160
|
|
|
127
|
-
When `
|
|
161
|
+
When `element="button"` is set, the tag renders as a `<button>`:
|
|
128
162
|
|
|
129
163
|
```tsx
|
|
130
164
|
const tag = screen.getByRole('button', { name: 'Category' });
|
|
131
165
|
```
|
|
132
166
|
|
|
167
|
+
When `element="a"` is set, the tag renders as a link:
|
|
168
|
+
|
|
169
|
+
```tsx
|
|
170
|
+
const tag = screen.getByRole('link', { name: 'Category' });
|
|
171
|
+
```
|
|
172
|
+
|
|
133
173
|
For deletable tags, query the delete button:
|
|
134
174
|
|
|
135
175
|
```tsx
|
|
@@ -4,18 +4,60 @@
|
|
|
4
4
|
|
|
5
5
|
Translate Figma design properties and structures into IDS (Iress Design System) component implementations. This skill helps AI agents interpret Figma design metadata (from tools like Figma MCP or exported design specs) and produce accurate IDS code.
|
|
6
6
|
|
|
7
|
+
## Figma MCP Setup
|
|
8
|
+
|
|
9
|
+
AI agents need a Figma MCP server to read Figma files directly. Without one, you can still use this skill by pasting exported design specs or Figma component descriptions manually.
|
|
10
|
+
|
|
11
|
+
### Setup
|
|
12
|
+
|
|
13
|
+
1. **Get a Figma personal access token** — In Figma, go to *Settings → Account → Personal access tokens* and create a token with **File content (Read-only)** scope.
|
|
14
|
+
|
|
15
|
+
2. **Add the MCP server to your agent config.** The exact location depends on your tool:
|
|
16
|
+
|
|
17
|
+
| Tool | Config file |
|
|
18
|
+
| --- | --- |
|
|
19
|
+
| **Kiro CLI** | `~/.kiro/settings/mcp.json` (global) or `.kiro/settings/mcp.json` (workspace) |
|
|
20
|
+
| **Cursor** | `.cursor/mcp.json` |
|
|
21
|
+
| **Claude Code** | `.claude/mcp.json` or `~/.claude/mcp.json` |
|
|
22
|
+
| **VS Code (GitHub Copilot)** | `.vscode/mcp.json` |
|
|
23
|
+
|
|
24
|
+
Example configuration (using the community [`figma-developer-mcp`](https://github.com/nicholasgriffintn/figma-developer-mcp) server):
|
|
25
|
+
|
|
26
|
+
```json
|
|
27
|
+
{
|
|
28
|
+
"mcpServers": {
|
|
29
|
+
"Figma": {
|
|
30
|
+
"command": "npx",
|
|
31
|
+
"args": ["-y", "figma-developer-mcp", "--stdio"],
|
|
32
|
+
"env": {
|
|
33
|
+
"FIGMA_API_KEY": "<your-figma-token>"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
For Kiro CLI, you can also add it via the command line:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
kiro-cli mcp add --name Figma --command npx --args "-y figma-developer-mcp --stdio" --env "FIGMA_API_KEY=<your-figma-token>"
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
3. **Verify** — Ask your agent to fetch data from a Figma file URL. It should return frame and component information.
|
|
47
|
+
|
|
7
48
|
## Process
|
|
8
49
|
|
|
9
50
|
1. **Analyse Figma structure** — Identify frames, auto-layout, and component instances
|
|
10
51
|
2. **Map components** — Match Figma component names/variants to IDS components
|
|
11
52
|
3. **Extract tokens** — Convert Figma design values to IDS design token references
|
|
12
|
-
4. **Generate code** — Produce clean React/TypeScript with proper IDS imports
|
|
53
|
+
4. **Generate code** — Produce clean, minimal React/TypeScript with proper IDS imports. Use the fewest components possible — check whether parent components already handle layout before adding `IressInline`/`IressStack` wrappers. Never wrap a single child in a layout component.
|
|
13
54
|
5. **Verify output** — Check that all imports resolve, no raw HTML is used where IDS components exist, grid layouts use responsive `span` values, and no common anti-patterns are present (disabled buttons, slot attributes, redundant textStyle)
|
|
14
55
|
|
|
15
56
|
> **Important:** IDS v6 is currently in beta. Install with the `@beta` tag:
|
|
16
57
|
>
|
|
17
58
|
> ```bash
|
|
18
59
|
> npm install @iress-oss/ids-components@beta
|
|
60
|
+
> npm install @iress-oss/ids-tokens@beta # if using tokens directly (e.g. cssVars or CSS vars import)
|
|
19
61
|
> ```
|
|
20
62
|
|
|
21
63
|
## Figma → IDS Mapping
|
|
@@ -48,11 +90,11 @@ When mapping Figma components to IDS, read references/component-mapping.md for t
|
|
|
48
90
|
| Input / Text | `IressField` + `IressInput` | label, placeholder |
|
|
49
91
|
| Input / Currency | `IressField` + `IressInputCurrency` | label |
|
|
50
92
|
| Select / Dropdown | `IressField` + `IressSelect` | label, options |
|
|
51
|
-
| Checkbox | `IressCheckbox` | label
|
|
52
|
-
| Checkbox Group | `IressCheckboxGroup` + `IressCheckbox`s | label
|
|
53
|
-
| Radio Group | `IressRadioGroup` + `IressRadio`s | label
|
|
54
|
-
| Toggle | `IressToggle` | label
|
|
55
|
-
| Card | `IressCard` |
|
|
93
|
+
| Checkbox | `IressCheckbox` | `children` for label |
|
|
94
|
+
| Checkbox Group | `IressCheckboxGroup` + `IressCheckbox`s | Wrap in `IressField` for label |
|
|
95
|
+
| Radio Group | `IressRadioGroup` + `IressRadio`s | Wrap in `IressField` for label |
|
|
96
|
+
| Toggle | `IressToggle` | `children` for label |
|
|
97
|
+
| Card | `IressCard` | `heading`, `footer` props; `children` for body |
|
|
56
98
|
| Panel | `IressPanel` | |
|
|
57
99
|
| Alert / Success | `IressAlert status="success"` | |
|
|
58
100
|
| Alert / Danger | `IressAlert status="danger"` | |
|
|
@@ -64,8 +106,8 @@ When mapping Figma components to IDS, read references/component-mapping.md for t
|
|
|
64
106
|
| Modal / Warning | `IressModal status="warning"` | actions, size sm/md only |
|
|
65
107
|
| Slideout / Drawer | `IressSlideout` | |
|
|
66
108
|
| Tabs | `IressTabSet` + `IressTab` | |
|
|
67
|
-
| Table | `IressTable` |
|
|
68
|
-
| Tag | `IressTag` | clickable
|
|
109
|
+
| Table | `IressTable` | Data-driven: `rows`, `columns`, `caption` props |
|
|
110
|
+
| Tag | `IressTag` | `bordered` for visible border; `element="button"` for clickable, `element="a"` for link; `onClick` alone also auto-renders as button |
|
|
69
111
|
| Pill | `IressPill` | |
|
|
70
112
|
| Tooltip | `IressTooltip` | |
|
|
71
113
|
| Icon | `IressIcon name="..."` | Material Symbols name |
|
|
@@ -131,19 +173,23 @@ IDS base spacing unit = 4px (0.25rem). Map Figma pixel values:
|
|
|
131
173
|
|
|
132
174
|
## Typography
|
|
133
175
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
|
137
|
-
|
|
|
138
|
-
| Heading /
|
|
139
|
-
| Heading /
|
|
140
|
-
| Heading /
|
|
141
|
-
|
|
|
142
|
-
|
|
|
143
|
-
| Body / MD
|
|
144
|
-
| Body /
|
|
145
|
-
| Body /
|
|
146
|
-
|
|
|
176
|
+
Prefer semantic HTML elements via the `element` prop — they convey meaning to screen readers. Only fall back to `textStyle` when no semantic element matches the visual treatment.
|
|
177
|
+
|
|
178
|
+
| Figma Text Style | IDS Token | Component |
|
|
179
|
+
| ---------------------------------- | ---------------------------- | ------------------------------------------------------------------------------------------------- |
|
|
180
|
+
| Heading / H1 (Ubuntu 24px/500) | `typography.heading.1` | `<IressText element="h1">` |
|
|
181
|
+
| Heading / H2 (Ubuntu 20px/500) | `typography.heading.2` | `<IressText element="h2">` |
|
|
182
|
+
| Heading / H3 (Ubuntu 18px/500) | `typography.heading.3` | `<IressText element="h3">` |
|
|
183
|
+
| Heading / H4 (Ubuntu 16px/500) | `typography.heading.4` | `<IressText element="h4">` |
|
|
184
|
+
| Heading / H5 (Ubuntu 16px/400) | `typography.heading.5` | `<IressText element="h5">` |
|
|
185
|
+
| Body / MD Regular (Inter 14px/400) | `typography.body.md.regular` | `<IressText>` (default) or `<IressText element="p">` for paragraph semantics |
|
|
186
|
+
| Body / MD Medium (Inter 14px/500) | `typography.body.md.medium` | `<IressText textStyle="typography.body.md.medium">` — use `textStyle` because there is no semantic medium element |
|
|
187
|
+
| Body / MD Strong (Inter 14px/600) | `typography.body.md.strong` | `<IressText element="strong">` — conveys emphasis to screen readers |
|
|
188
|
+
| Body / SM Regular (Inter 12px/400) | `typography.body.sm` | `<IressText element="small">` — conveys fine print / secondary text |
|
|
189
|
+
| Body / SM Strong (Inter 12px/600) | `typography.body.sm.strong` | `<IressText element="small"><strong>...</strong></IressText>` |
|
|
190
|
+
| Code (Space 16px/400) | `typography.code` | `<IressText element="code">` |
|
|
191
|
+
|
|
192
|
+
> **When to use `textStyle`:** Only when you need to visually override the default styling of a semantic element — e.g. making an `h2` look like an `h4` for visual hierarchy while keeping the correct heading level for accessibility: `<IressText element="h2" textStyle="typography.heading.4">`.
|
|
147
193
|
|
|
148
194
|
> **Tip:** When translating Figma frames that contain mixed or unstructured text (e.g. CMS content, markdown, rich text blocks), wrap the content in `IressText` and nest native HTML elements (`<p>`, `<strong>`, `<a>`, `<ul>`, etc.) inside it. This is an allowed pattern that lets `IressText` apply consistent typography while preserving the original content structure.
|
|
149
195
|
|
|
@@ -175,8 +221,8 @@ import {
|
|
|
175
221
|
|
|
176
222
|
function LoginForm() {
|
|
177
223
|
return (
|
|
178
|
-
<IressCard p="
|
|
179
|
-
<IressStack gap="
|
|
224
|
+
<IressCard p="lg">
|
|
225
|
+
<IressStack gap="md">
|
|
180
226
|
<IressText element="h2">Log In</IressText>
|
|
181
227
|
<IressField label="Email" htmlFor="email" required>
|
|
182
228
|
<IressInput id="email" type="email" />
|
|
@@ -255,39 +301,41 @@ import { IressModal } from '@iress-oss/ids-components';
|
|
|
255
301
|
|
|
256
302
|
```tsx
|
|
257
303
|
import { IressTable, IressTag, IressButton } from '@iress-oss/ids-components';
|
|
304
|
+
import type { TableColumn } from '@iress-oss/ids-components';
|
|
258
305
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
);
|
|
306
|
+
interface User {
|
|
307
|
+
name: string;
|
|
308
|
+
email: string;
|
|
309
|
+
status: string;
|
|
310
|
+
id: string;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
const columns: TableColumn<User>[] = [
|
|
314
|
+
{ key: 'name', label: 'Name' },
|
|
315
|
+
{ key: 'email', label: 'Email' },
|
|
316
|
+
{
|
|
317
|
+
key: 'status',
|
|
318
|
+
label: 'Status',
|
|
319
|
+
format: (value) => <IressTag>{value}</IressTag>,
|
|
320
|
+
},
|
|
321
|
+
{
|
|
322
|
+
key: 'actions',
|
|
323
|
+
label: 'Actions',
|
|
324
|
+
format: (_, row) => (
|
|
325
|
+
<IressButton mode="tertiary" icon="edit">
|
|
326
|
+
Edit
|
|
327
|
+
</IressButton>
|
|
328
|
+
),
|
|
329
|
+
},
|
|
330
|
+
];
|
|
331
|
+
|
|
332
|
+
function UsersTable({ users }: { users: User[] }) {
|
|
333
|
+
return <IressTable caption="Users" rows={users} columns={columns} />;
|
|
288
334
|
}
|
|
289
335
|
```
|
|
290
336
|
|
|
337
|
+
> **Key insight:** `IressTable` is data-driven — pass `rows` and `columns` props instead of composing sub-components. Use the `format` function on columns to render custom cell content like tags or buttons.
|
|
338
|
+
|
|
291
339
|
## Responsive Layout
|
|
292
340
|
|
|
293
341
|
**Always produce responsive output**, even when Figma only provides a single desktop frame. IDS uses a 12-column grid with 6 breakpoints — every translation should consider how the layout adapts to smaller screens.
|
|
@@ -350,10 +398,12 @@ When Figma provides separate mobile and desktop frames for the same layout:
|
|
|
350
398
|
When Figma only provides a desktop frame with a sidebar + main content area, infer the mobile layout:
|
|
351
399
|
|
|
352
400
|
```tsx
|
|
401
|
+
import { useState } from 'react';
|
|
353
402
|
import {
|
|
354
403
|
useBreakpoint,
|
|
355
404
|
IressSlideout,
|
|
356
405
|
IressButton,
|
|
406
|
+
IressStack,
|
|
357
407
|
IressRow,
|
|
358
408
|
IressCol,
|
|
359
409
|
} from '@iress-oss/ids-components';
|
|
@@ -367,7 +417,7 @@ function Page() {
|
|
|
367
417
|
<>
|
|
368
418
|
{isMobile ? (
|
|
369
419
|
// Mobile: primary content first, secondary content in slideout
|
|
370
|
-
<IressStack gap="
|
|
420
|
+
<IressStack gap="md">
|
|
371
421
|
<IressButton
|
|
372
422
|
mode="secondary"
|
|
373
423
|
icon="filter_list"
|
|
@@ -424,17 +474,42 @@ function Navigation() {
|
|
|
424
474
|
|
|
425
475
|
## Best Practices
|
|
426
476
|
|
|
427
|
-
1. **Use
|
|
428
|
-
2. **
|
|
429
|
-
3. **
|
|
430
|
-
4. **
|
|
431
|
-
5. **
|
|
432
|
-
6. **
|
|
433
|
-
7. **
|
|
434
|
-
8. **
|
|
477
|
+
1. **Minimise component nesting** — Use the fewest components possible. Every wrapper must earn its place. Before adding `IressInline` or `IressStack`, check whether the parent already handles layout (e.g. `IressCard` has `heading` and `footer` props; `IressModal` has `actions`; `IressButtonGroup` handles horizontal button layout). Don't wrap a single child in a layout component.
|
|
478
|
+
2. **Use IDS components, not raw elements** — IDS components encapsulate correct spacing, colours, border radius, and accessibility
|
|
479
|
+
3. **Don't recreate component internals** — If Figma shows a button with specific padding/radius, use `IressButton` with the right `mode` — the styling is built in
|
|
480
|
+
4. **Map Figma gap/padding to spacing tokens** — Divide pixel value by 4 to get the token number, then use the full token: 16px → `"spacing.4"`, 24px → `"spacing.6"`. Alias tokens (`"xs"`, `"sm"`, `"md"`, `"lg"`, `"xl"`) are also valid. Never use bare numbers like `gap="4"`.
|
|
481
|
+
5. **Prefer semantic props over manual styling** — Use `status="danger"` instead of `bg="colour.system.danger.fill"`
|
|
482
|
+
6. **Use IressField for all form inputs** — It provides the label, hint, and validation layout
|
|
483
|
+
7. **Respect responsive patterns** — Use `hideFrom`/`hideBelow` props or the `useBreakpoint` hook for responsive visibility; use responsive `span` on `IressCol` for adaptive grid layouts
|
|
484
|
+
8. **Always make grid layouts responsive** — When translating Figma multi-column layouts, use responsive `span` values (e.g. `span={{ xs: 12, md: 6 }}`) so columns stack on mobile
|
|
485
|
+
9. **Check the component docs** — Read the specific component doc for detailed props and patterns (`node_modules/@iress-oss/ids-components/.ai/components/`)
|
|
435
486
|
|
|
436
487
|
## Common Mistakes
|
|
437
488
|
|
|
489
|
+
### Unnecessary layout wrappers
|
|
490
|
+
|
|
491
|
+
Don't add `IressInline` or `IressStack` when it adds no value. Every Figma auto-layout frame does NOT need its own layout wrapper — check the IDS component first.
|
|
492
|
+
|
|
493
|
+
```tsx
|
|
494
|
+
// ❌ Unnecessary nesting — IressStack wrapping a single child
|
|
495
|
+
<IressStack gap="md">
|
|
496
|
+
<IressInline gap="sm">
|
|
497
|
+
<IressButton mode="primary">Save</IressButton>
|
|
498
|
+
<IressButton mode="secondary">Cancel</IressButton>
|
|
499
|
+
</IressInline>
|
|
500
|
+
</IressStack>
|
|
501
|
+
|
|
502
|
+
// ✅ Single group of buttons only needs IressInline
|
|
503
|
+
<IressInline gap="sm">
|
|
504
|
+
<IressButton mode="primary">Save</IressButton>
|
|
505
|
+
<IressButton mode="secondary">Cancel</IressButton>
|
|
506
|
+
</IressInline>
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
**Rule of thumb:** When Figma shows an auto-layout frame, check if the corresponding IDS component already provides that layout before adding a wrapper. Components like `IressModal` (with `actions`) and `IressButtonGroup` already handle their internal layout. For `IressCard`, use the `heading` and `footer` props to structure content — but note the `footer` slot does not auto-layout its children, so use `IressInline` inside `footer` when you need horizontal button layout.
|
|
510
|
+
|
|
511
|
+
### Other common anti-patterns
|
|
512
|
+
|
|
438
513
|
For the full list of common anti-patterns (disabled buttons, redundant textStyle, legacy slot attributes, raw HTML, hardcoded values), read the Common Mistakes guide at `node_modules/@iress-oss/ids-components/.ai/guides/foundations-common-mistakes.md` (requires `@iress-oss/ids-components` to be installed).
|
|
439
514
|
|
|
440
515
|
**Figma-specific addition:** When Figma shows named content areas ("prepend", "append", "footer"), map them to the corresponding **React prop**, not to a `slot` attribute. When Figma shows a greyed-out or disabled button state, do not use `disabled` — see the guide for alternatives.
|