@discourser/design-system 0.22.2 → 0.22.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.
Files changed (75) hide show
  1. package/dist/figma-codex.json +2 -2
  2. package/docs/CSS_USAGE.md +235 -0
  3. package/docs/FIGMA_MAKE_SETUP.md +339 -0
  4. package/docs/GUIDELINES_REVIEW.md +728 -0
  5. package/docs/MAINTAINER_CHECKLIST.md +265 -0
  6. package/docs/TESTING_QUICK_REFERENCE.md +159 -0
  7. package/docs/TESTING_TOKENS.md +340 -0
  8. package/docs/active-stories/README.md +29 -0
  9. package/docs/active-stories/STORY-006a-figma-translation-foundations.md +324 -0
  10. package/docs/active-stories/STORY-006b-figma-translation-components.md +201 -0
  11. package/docs/active-stories/STORY-006c-figma-translation-layout-extension.md +258 -0
  12. package/docs/active-stories/STORY-008-kai-sidecar-fragments.md +137 -0
  13. package/docs/active-stories/STORY-011-verify-translation-docs.md +182 -0
  14. package/docs/archive/ARCHITECTURE-discourser-design-system.md +448 -0
  15. package/docs/claude-feed-back/ARCHITECTURE_DIAGRAM.md +243 -0
  16. package/docs/claude-feed-back/STYLING_VERIFICATION.md +89 -0
  17. package/docs/claude-feed-back/TEST_RESULTS.md +182 -0
  18. package/docs/context-share/ELEVATION_FIX_PLAN.md +903 -0
  19. package/docs/context-share/STORY-001-VALIDATION-PASSED.md +192 -0
  20. package/docs/context-share/STORY-002-IMPLEMENTATION-COMPLETE.md +161 -0
  21. package/docs/context-share/STORYBOOK_MCP_STRATEGY.md +867 -0
  22. package/docs/context-share/TESTING_GAPS_FILLED.md +353 -0
  23. package/docs/context-share/TOKEN_TESTING_SUMMARY.md +388 -0
  24. package/docs/context-share/code-connect-prompt.md +90 -0
  25. package/docs/context-share/dds-autonomous-pipeline.md +765 -0
  26. package/docs/context-share/fix-checkbox-radio-tokens.md +145 -0
  27. package/docs/context-share/icon-component-prompt.md +154 -0
  28. package/docs/context-share/icons/Audience.svg +3 -0
  29. package/docs/context-share/icons/AudioSpeaker.svg +3 -0
  30. package/docs/context-share/icons/BookmarkPlus.svg +3 -0
  31. package/docs/context-share/icons/ClipBoard.svg +8 -0
  32. package/docs/context-share/icons/DiscourserLogo.svg +4 -0
  33. package/docs/context-share/icons/ExitStudio.svg +4 -0
  34. package/docs/context-share/icons/Microphone.svg +5 -0
  35. package/docs/context-share/icons/NotebookPen.svg +3 -0
  36. package/docs/context-share/icons/PausePlay.svg +5 -0
  37. package/docs/context-share/icons/Play.svg +4 -0
  38. package/docs/context-share/icons/Record.svg +6 -0
  39. package/docs/context-share/icons/RepeatQuestion.svg +3 -0
  40. package/docs/context-share/icons/ScrollText.svg +3 -0
  41. package/docs/context-share/icons/Sparkles.svg +3 -0
  42. package/docs/context-share/icons/Speech.svg +3 -0
  43. package/docs/context-share/icons/StopPlay.svg +4 -0
  44. package/docs/context-share/icons/Timer.svg +3 -0
  45. package/docs/context-share/icons/UserProfile.svg +3 -0
  46. package/docs/context-share/m3-token-pipeline-audit.md +125 -0
  47. package/docs/context-share/storybook-mcp-kai-agent-revised-summary.md +211 -0
  48. package/docs/discourser-design-system-prd.md +3698 -0
  49. package/docs/figma-captures/01-typography.png +0 -0
  50. package/docs/figma-captures/02-button-iconbutton.png +0 -0
  51. package/docs/figma-captures/03-form-inputs.png +0 -0
  52. package/docs/figma-captures/04-form-controls.png +0 -0
  53. package/docs/figma-captures/05-data-display.png +0 -0
  54. package/docs/figma-captures/06-feedback.png +0 -0
  55. package/docs/figma-captures/07-overlays.png +0 -0
  56. package/docs/figma-captures/08-navigation-layout.png +0 -0
  57. package/docs/figma-captures/09-custom-components.png +0 -0
  58. package/docs/figma-captures/10-scenario-queue.png +0 -0
  59. package/docs/figma-captures/11-icon-library.png +0 -0
  60. package/docs/figma-make-docs/01-understanding-templates.md +235 -0
  61. package/docs/figma-make-docs/02-prerequisites.md +266 -0
  62. package/docs/figma-make-docs/03-creating-template.md +306 -0
  63. package/docs/figma-make-docs/04-adding-guidelines.md +448 -0
  64. package/docs/figma-make-docs/05-example-starter-code.md +590 -0
  65. package/docs/figma-make-docs/06-publishing-template.md +417 -0
  66. package/docs/figma-make-docs/07-maintenance.md +536 -0
  67. package/docs/figma-make-docs/08-faq.md +490 -0
  68. package/docs/figma-make-docs/README.md +95 -0
  69. package/docs/material-theme.json +418 -0
  70. package/docs/plans/2026-03-12-figma-token-export-rewrite.md +504 -0
  71. package/docs/plans/2026-03-12-step7-panda-token-resolution-design.md +119 -0
  72. package/docs/plans/2026-03-12-step7-panda-token-resolution.md +993 -0
  73. package/docs/token-name-mapping.json +850 -0
  74. package/docs/token-name-mapping.md +251 -0
  75. package/package.json +3 -2
@@ -0,0 +1,765 @@
1
+ # DDS Code to Canvas + Code Connect — Autonomous Pipeline
2
+
3
+ > **IMPORTANT**: Execute ALL phases sequentially without stopping to ask for confirmation. Do NOT pause to ask "should I proceed?" or "would you like me to continue?" — just keep going. If a phase fails verification, fix it and retry before moving to the next phase. Only stop if you hit 3 consecutive failures on the same step.
4
+
5
+ > **CONTEXT**: Phase 1 (adding ScenarioQueue to the FullCatalog) was already completed and verified in a prior session. This pipeline covers Phase 2 (Code to Canvas) and Phase 3 (Code Connect setup).
6
+
7
+ > **FIGMA TOKEN**: Available in `.env` file as `FIGMA_ACCESS_TOKEN`. Load it with `source .env` or `export $(cat .env | xargs)` if needed for CLI commands.
8
+
9
+ ---
10
+
11
+ ## Pre-Flight Checks
12
+
13
+ Before starting any phase, verify the environment is ready. Do all of these first:
14
+
15
+ ### A. Verify Figma MCP is connected
16
+
17
+ Check that the Figma desktop MCP tools are available. You should have access to tools like `get_design_context`, `get_metadata`, `get_screenshot`, and importantly **write tools** for creating frames on the canvas. If the Figma MCP tools are not available, STOP and report that the Figma desktop MCP server is not connected — the user needs to enable it in Figma Dev Mode.
18
+
19
+ ### B. Verify Storybook is running
20
+
21
+ ```bash
22
+ curl -s -o /dev/null -w "%{http_code}" http://localhost:6006 || echo "NOT_RUNNING"
23
+ ```
24
+
25
+ If not running:
26
+ ```bash
27
+ pnpm storybook &
28
+ sleep 15
29
+ # Verify it's up
30
+ curl -s -o /dev/null -w "%{http_code}" http://localhost:6006
31
+ ```
32
+
33
+ ### C. Verify Phase 1 is complete
34
+
35
+ ```bash
36
+ # Check that ScenarioQueue is in the catalog
37
+ grep -c "ScenarioQueue" stories/ComponentCatalog.stories.tsx
38
+ ```
39
+
40
+ Should return a number > 0. If it returns 0, something went wrong with the prior session — but do NOT redo Phase 1, just note it and proceed.
41
+
42
+ ---
43
+
44
+ ## Phase 2: Code to Canvas — Push FullCatalog to Figma
45
+
46
+ **Goal**: Capture the rendered FullCatalog from Storybook and push each section into the Figma file as editable frames.
47
+
48
+ **Target Figma file**: `https://www.figma.com/design/ua4LYtQHXt2lhHlCsSpdBm/V2-Discourser-FigmaLoop?node-id=0-1`
49
+ **File key**: `ua4LYtQHXt2lhHlCsSpdBm`
50
+
51
+ ### 2A. Understand the catalog sections
52
+
53
+ The FullCatalog at `http://localhost:6006/?path=/story/design-system-component-catalog--full-catalog` contains these sections (in order):
54
+
55
+ 1. **Typography** — Header component, 11 sizes
56
+ 2. **Button & IconButton** — 6 variants × 7 sizes × 5 color palettes, states, ButtonGroup
57
+ 3. **Form Inputs** — Input, InputGroup, Textarea
58
+ 4. **Form Controls** — RadioGroup, Checkbox, Switch, Select, Slider
59
+ 5. **Data Display** — Card, Badge, Avatar, Progress, Skeleton
60
+ 6. **Feedback** — Spinner, CloseButton, Toast triggers, loading states
61
+ 7. **Overlays** — Dialog, Drawer, Popover, Tooltip
62
+ 8. **Navigation & Layout** — Breadcrumb, Accordion, Tabs, Stepper
63
+ 9. **Custom Components** — ContentCard, NavigationMenu, ScenarioSettings, Stepper with content
64
+ 10. **ScenarioQueue** — Full queue component, individual ScenarioCards
65
+ 11. **Icon Library** — All 9 DDS icons
66
+
67
+ ### 2B. Capture and push to Figma
68
+
69
+ Use the browser/devtools MCP to navigate to the Storybook FullCatalog URL at 1440px viewport width. Then use the Figma MCP write tools to push the captured UI into the target Figma file.
70
+
71
+ **Approach — for each section:**
72
+ 1. Use the browser MCP to navigate to the FullCatalog story
73
+ 2. Scroll to the section, take a screenshot or capture the rendered state
74
+ 3. Use the Figma MCP to create a new frame on the canvas for that section
75
+ 4. Name each frame clearly: `DDS / Typography`, `DDS / Button & IconButton`, `DDS / Form Inputs`, etc.
76
+
77
+ If the Figma MCP provides a "capture from browser" or "code to canvas" tool, use that directly — it will produce higher fidelity editable layers rather than rasterized screenshots.
78
+
79
+ If you cannot find write tools on the Figma MCP (only read tools are available), then:
80
+ - Document which tools ARE available
81
+ - Take screenshots of each section via browser MCP
82
+ - Save them to `docs/figma-captures/` as PNG files for manual import
83
+ - Report this in the summary and move on to Phase 3
84
+
85
+ ### 2C. Verify Phase 2
86
+
87
+ Use `get_metadata` on the Figma file (node `0-1`) to confirm frames were created. List them by name.
88
+
89
+ ---
90
+
91
+ ## Phase 3: Code Connect Setup
92
+
93
+ **Goal**: Set up Figma Code Connect so that Figma Dev Mode shows correct DDS React imports and usage examples when inspecting components.
94
+
95
+ ### 3A. Install Code Connect
96
+
97
+ ```bash
98
+ pnpm add -D @figma/code-connect
99
+ ```
100
+
101
+ ### 3B. Create `figma.config.json` at project root
102
+
103
+ ```json
104
+ {
105
+ "codeConnect": {
106
+ "parser": "react",
107
+ "include": ["src/components/**/*.figma.tsx"],
108
+ "importPaths": {
109
+ "src/components/*": "@discourser/design-system"
110
+ }
111
+ }
112
+ }
113
+ ```
114
+
115
+ ### 3C. Create `.figma.tsx` annotation files
116
+
117
+ Create one `.figma.tsx` file per component. These map Figma components to real code. The `figmaNodeUrl` values use the file URL as a base — they'll be refined once components exist as Figma component nodes.
118
+
119
+ **Base URL for all**: `https://www.figma.com/design/ua4LYtQHXt2lhHlCsSpdBm`
120
+
121
+ Create ALL of the following files. Do not skip any. Do not stop to ask if you should continue.
122
+
123
+ ---
124
+
125
+ #### `src/components/Button.figma.tsx`
126
+ ```tsx
127
+ import figma from '@figma/code-connect'
128
+ import { Button } from './Button'
129
+
130
+ figma.connect(Button, 'https://www.figma.com/design/ua4LYtQHXt2lhHlCsSpdBm', {
131
+ props: {
132
+ variant: figma.enum('Variant', {
133
+ Solid: 'solid', Elevated: 'elevated', Surface: 'surface',
134
+ Subtle: 'subtle', Outline: 'outline', Plain: 'plain',
135
+ }),
136
+ colorPalette: figma.enum('Color Palette', {
137
+ Primary: 'primary', Secondary: 'secondary', Tertiary: 'tertiary',
138
+ Neutral: 'neutral', Error: 'error',
139
+ }),
140
+ size: figma.enum('Size', {
141
+ '2xs': '2xs', xs: 'xs', sm: 'sm', md: 'md', lg: 'lg', xl: 'xl', '2xl': '2xl',
142
+ }),
143
+ disabled: figma.boolean('Disabled'),
144
+ loading: figma.boolean('Loading'),
145
+ label: figma.string('Label'),
146
+ },
147
+ example: ({ variant, colorPalette, size, disabled, loading, label }) => (
148
+ <Button variant={variant} colorPalette={colorPalette} size={size} disabled={disabled} loading={loading}>
149
+ {label}
150
+ </Button>
151
+ ),
152
+ })
153
+ ```
154
+
155
+ #### `src/components/IconButton.figma.tsx`
156
+ ```tsx
157
+ import figma from '@figma/code-connect'
158
+ import { IconButton } from './IconButton'
159
+
160
+ figma.connect(IconButton, 'https://www.figma.com/design/ua4LYtQHXt2lhHlCsSpdBm', {
161
+ props: {
162
+ variant: figma.enum('Variant', {
163
+ Solid: 'solid', Elevated: 'elevated', Surface: 'surface',
164
+ Subtle: 'subtle', Outline: 'outline', Plain: 'plain',
165
+ }),
166
+ colorPalette: figma.enum('Color Palette', {
167
+ Primary: 'primary', Secondary: 'secondary', Tertiary: 'tertiary',
168
+ Neutral: 'neutral', Error: 'error',
169
+ }),
170
+ size: figma.enum('Size', {
171
+ '2xs': '2xs', xs: 'xs', sm: 'sm', md: 'md', lg: 'lg', xl: 'xl', '2xl': '2xl',
172
+ }),
173
+ },
174
+ example: ({ variant, colorPalette, size }) => (
175
+ <IconButton variant={variant} colorPalette={colorPalette} size={size} aria-label="Action">
176
+ {/* icon */}
177
+ </IconButton>
178
+ ),
179
+ })
180
+ ```
181
+
182
+ #### `src/components/Input.figma.tsx`
183
+ ```tsx
184
+ import figma from '@figma/code-connect'
185
+ import { Input } from './Input'
186
+
187
+ figma.connect(Input, 'https://www.figma.com/design/ua4LYtQHXt2lhHlCsSpdBm', {
188
+ props: {
189
+ size: figma.enum('Size', { sm: 'sm', md: 'md', lg: 'lg', xl: 'xl', '2xl': '2xl' }),
190
+ disabled: figma.boolean('Disabled'),
191
+ placeholder: figma.string('Placeholder'),
192
+ },
193
+ example: ({ size, disabled, placeholder }) => (
194
+ <Input size={size} disabled={disabled} placeholder={placeholder} />
195
+ ),
196
+ })
197
+ ```
198
+
199
+ #### `src/components/Textarea.figma.tsx`
200
+ ```tsx
201
+ import figma from '@figma/code-connect'
202
+ import { Textarea } from './Textarea'
203
+
204
+ figma.connect(Textarea, 'https://www.figma.com/design/ua4LYtQHXt2lhHlCsSpdBm', {
205
+ props: {
206
+ disabled: figma.boolean('Disabled'),
207
+ placeholder: figma.string('Placeholder'),
208
+ },
209
+ example: ({ disabled, placeholder }) => (
210
+ <Textarea disabled={disabled} placeholder={placeholder} rows={3} />
211
+ ),
212
+ })
213
+ ```
214
+
215
+ #### `src/components/Header.figma.tsx`
216
+ ```tsx
217
+ import figma from '@figma/code-connect'
218
+ import { Header } from './Header'
219
+
220
+ figma.connect(Header, 'https://www.figma.com/design/ua4LYtQHXt2lhHlCsSpdBm', {
221
+ props: {
222
+ size: figma.enum('Size', {
223
+ '7xl': '7xl', '6xl': '6xl', '5xl': '5xl', '4xl': '4xl',
224
+ '3xl': '3xl', '2xl': '2xl', xl: 'xl', lg: 'lg',
225
+ md: 'md', sm: 'sm', xs: 'xs',
226
+ }),
227
+ children: figma.string('Text'),
228
+ },
229
+ example: ({ size, children }) => <Header size={size}>{children}</Header>,
230
+ })
231
+ ```
232
+
233
+ #### `src/components/Badge.figma.tsx`
234
+ ```tsx
235
+ import figma from '@figma/code-connect'
236
+ import { Badge } from './Badge'
237
+
238
+ figma.connect(Badge, 'https://www.figma.com/design/ua4LYtQHXt2lhHlCsSpdBm', {
239
+ props: {
240
+ variant: figma.enum('Variant', { Solid: 'solid', Subtle: 'subtle', Outline: 'outline' }),
241
+ colorPalette: figma.enum('Color Palette', {
242
+ Primary: 'primary', Secondary: 'secondary', Tertiary: 'tertiary',
243
+ Neutral: 'neutral', Error: 'error',
244
+ }),
245
+ size: figma.enum('Size', { sm: 'sm', md: 'md', lg: 'lg', xl: 'xl' }),
246
+ label: figma.string('Label'),
247
+ },
248
+ example: ({ variant, colorPalette, size, label }) => (
249
+ <Badge variant={variant} colorPalette={colorPalette} size={size}>{label}</Badge>
250
+ ),
251
+ })
252
+ ```
253
+
254
+ #### `src/components/Spinner.figma.tsx`
255
+ ```tsx
256
+ import figma from '@figma/code-connect'
257
+ import { Spinner } from './Spinner'
258
+
259
+ figma.connect(Spinner, 'https://www.figma.com/design/ua4LYtQHXt2lhHlCsSpdBm', {
260
+ props: {
261
+ size: figma.enum('Size', { xs: 'xs', sm: 'sm', md: 'md', lg: 'lg', xl: 'xl' }),
262
+ colorPalette: figma.enum('Color Palette', {
263
+ Primary: 'primary', Secondary: 'secondary', Tertiary: 'tertiary',
264
+ Neutral: 'neutral', Error: 'error',
265
+ }),
266
+ },
267
+ example: ({ size, colorPalette }) => <Spinner size={size} colorPalette={colorPalette} />,
268
+ })
269
+ ```
270
+
271
+ #### `src/components/Card.figma.tsx`
272
+ ```tsx
273
+ import figma from '@figma/code-connect'
274
+ import * as Card from './Card'
275
+
276
+ figma.connect(Card.Root, 'https://www.figma.com/design/ua4LYtQHXt2lhHlCsSpdBm', {
277
+ props: {
278
+ variant: figma.enum('Variant', { Elevated: 'elevated', Outline: 'outline', Subtle: 'subtle' }),
279
+ },
280
+ example: ({ variant }) => (
281
+ <Card.Root variant={variant}>
282
+ <Card.Header>
283
+ <Card.Title>Title</Card.Title>
284
+ <Card.Description>Description</Card.Description>
285
+ </Card.Header>
286
+ <Card.Body>Content</Card.Body>
287
+ <Card.Footer>Footer</Card.Footer>
288
+ </Card.Root>
289
+ ),
290
+ })
291
+ ```
292
+
293
+ #### `src/components/Checkbox.figma.tsx`
294
+ ```tsx
295
+ import figma from '@figma/code-connect'
296
+ import * as Checkbox from './Checkbox'
297
+
298
+ figma.connect(Checkbox.Root, 'https://www.figma.com/design/ua4LYtQHXt2lhHlCsSpdBm', {
299
+ props: {
300
+ colorPalette: figma.enum('Color Palette', {
301
+ Primary: 'primary', Secondary: 'secondary', Tertiary: 'tertiary',
302
+ Neutral: 'neutral', Error: 'error',
303
+ }),
304
+ disabled: figma.boolean('Disabled'),
305
+ label: figma.string('Label'),
306
+ },
307
+ example: ({ colorPalette, disabled, label }) => (
308
+ <Checkbox.Root colorPalette={colorPalette} disabled={disabled}>
309
+ <Checkbox.Control><Checkbox.Indicator /></Checkbox.Control>
310
+ <Checkbox.Label>{label}</Checkbox.Label>
311
+ <Checkbox.HiddenInput />
312
+ </Checkbox.Root>
313
+ ),
314
+ })
315
+ ```
316
+
317
+ #### `src/components/Switch.figma.tsx`
318
+ ```tsx
319
+ import figma from '@figma/code-connect'
320
+ import * as Switch from './Switch'
321
+
322
+ figma.connect(Switch.Root, 'https://www.figma.com/design/ua4LYtQHXt2lhHlCsSpdBm', {
323
+ props: {
324
+ colorPalette: figma.enum('Color Palette', {
325
+ Primary: 'primary', Secondary: 'secondary', Tertiary: 'tertiary',
326
+ Neutral: 'neutral', Error: 'error',
327
+ }),
328
+ disabled: figma.boolean('Disabled'),
329
+ label: figma.string('Label'),
330
+ },
331
+ example: ({ colorPalette, disabled, label }) => (
332
+ <Switch.Root colorPalette={colorPalette} disabled={disabled}>
333
+ <Switch.Control><Switch.Thumb /></Switch.Control>
334
+ <Switch.Label>{label}</Switch.Label>
335
+ <Switch.HiddenInput />
336
+ </Switch.Root>
337
+ ),
338
+ })
339
+ ```
340
+
341
+ #### `src/components/Tabs.figma.tsx`
342
+ ```tsx
343
+ import figma from '@figma/code-connect'
344
+ import * as Tabs from './Tabs'
345
+
346
+ figma.connect(Tabs.Root, 'https://www.figma.com/design/ua4LYtQHXt2lhHlCsSpdBm', {
347
+ example: () => (
348
+ <Tabs.Root defaultValue="tab1">
349
+ <Tabs.List>
350
+ <Tabs.Trigger value="tab1">Tab 1</Tabs.Trigger>
351
+ <Tabs.Trigger value="tab2">Tab 2</Tabs.Trigger>
352
+ <Tabs.Indicator />
353
+ </Tabs.List>
354
+ <Tabs.Content value="tab1">Content 1</Tabs.Content>
355
+ <Tabs.Content value="tab2">Content 2</Tabs.Content>
356
+ </Tabs.Root>
357
+ ),
358
+ })
359
+ ```
360
+
361
+ #### `src/components/Accordion.figma.tsx`
362
+ ```tsx
363
+ import figma from '@figma/code-connect'
364
+ import * as Accordion from './Accordion'
365
+
366
+ figma.connect(Accordion.Root, 'https://www.figma.com/design/ua4LYtQHXt2lhHlCsSpdBm', {
367
+ example: () => (
368
+ <Accordion.Root collapsible>
369
+ <Accordion.Item value="item-1">
370
+ <Accordion.ItemTrigger>
371
+ <span>Trigger</span>
372
+ <Accordion.ItemIndicator />
373
+ </Accordion.ItemTrigger>
374
+ <Accordion.ItemContent>Content</Accordion.ItemContent>
375
+ </Accordion.Item>
376
+ </Accordion.Root>
377
+ ),
378
+ })
379
+ ```
380
+
381
+ #### `src/components/Dialog.figma.tsx`
382
+ ```tsx
383
+ import figma from '@figma/code-connect'
384
+ import * as Dialog from './Dialog'
385
+
386
+ figma.connect(Dialog.Root, 'https://www.figma.com/design/ua4LYtQHXt2lhHlCsSpdBm', {
387
+ example: () => (
388
+ <Dialog.Root>
389
+ <Dialog.Trigger asChild><button>Open</button></Dialog.Trigger>
390
+ <Dialog.Backdrop />
391
+ <Dialog.Positioner>
392
+ <Dialog.Content>
393
+ <Dialog.Header>
394
+ <Dialog.Title>Title</Dialog.Title>
395
+ <Dialog.CloseTrigger />
396
+ </Dialog.Header>
397
+ <Dialog.Body>Content</Dialog.Body>
398
+ </Dialog.Content>
399
+ </Dialog.Positioner>
400
+ </Dialog.Root>
401
+ ),
402
+ })
403
+ ```
404
+
405
+ #### `src/components/Drawer.figma.tsx`
406
+ ```tsx
407
+ import figma from '@figma/code-connect'
408
+ import * as Drawer from './Drawer'
409
+
410
+ figma.connect(Drawer.Root, 'https://www.figma.com/design/ua4LYtQHXt2lhHlCsSpdBm', {
411
+ example: () => (
412
+ <Drawer.Root>
413
+ <Drawer.Trigger asChild><button>Open</button></Drawer.Trigger>
414
+ <Drawer.Backdrop />
415
+ <Drawer.Positioner>
416
+ <Drawer.Content>
417
+ <Drawer.Header>
418
+ <Drawer.Title>Title</Drawer.Title>
419
+ <Drawer.CloseTrigger />
420
+ </Drawer.Header>
421
+ <Drawer.Body>Content</Drawer.Body>
422
+ </Drawer.Content>
423
+ </Drawer.Positioner>
424
+ </Drawer.Root>
425
+ ),
426
+ })
427
+ ```
428
+
429
+ #### `src/components/Select.figma.tsx`
430
+ ```tsx
431
+ import figma from '@figma/code-connect'
432
+ import * as Select from './Select'
433
+
434
+ figma.connect(Select.Root, 'https://www.figma.com/design/ua4LYtQHXt2lhHlCsSpdBm', {
435
+ example: () => (
436
+ <Select.Root collection={collection}>
437
+ <Select.Label>Label</Select.Label>
438
+ <Select.Control>
439
+ <Select.Trigger>
440
+ <Select.ValueText placeholder="Select..." />
441
+ <Select.Indicator />
442
+ </Select.Trigger>
443
+ </Select.Control>
444
+ <Select.Positioner>
445
+ <Select.Content>
446
+ <Select.ItemGroup>
447
+ <Select.Item item={item}>
448
+ <Select.ItemText>{item.label}</Select.ItemText>
449
+ </Select.Item>
450
+ </Select.ItemGroup>
451
+ </Select.Content>
452
+ </Select.Positioner>
453
+ <Select.HiddenSelect />
454
+ </Select.Root>
455
+ ),
456
+ })
457
+ ```
458
+
459
+ #### `src/components/Slider.figma.tsx`
460
+ ```tsx
461
+ import figma from '@figma/code-connect'
462
+ import * as Slider from './Slider'
463
+
464
+ figma.connect(Slider.Root, 'https://www.figma.com/design/ua4LYtQHXt2lhHlCsSpdBm', {
465
+ props: {
466
+ colorPalette: figma.enum('Color Palette', {
467
+ Primary: 'primary', Secondary: 'secondary', Tertiary: 'tertiary',
468
+ Neutral: 'neutral', Error: 'error',
469
+ }),
470
+ },
471
+ example: ({ colorPalette }) => (
472
+ <Slider.Root colorPalette={colorPalette}>
473
+ <Slider.Label>Label</Slider.Label>
474
+ <Slider.ValueText />
475
+ <Slider.Control>
476
+ <Slider.Track><Slider.Range /></Slider.Track>
477
+ <Slider.Thumb index={0}><Slider.HiddenInput /></Slider.Thumb>
478
+ </Slider.Control>
479
+ </Slider.Root>
480
+ ),
481
+ })
482
+ ```
483
+
484
+ #### `src/components/RadioGroup.figma.tsx`
485
+ ```tsx
486
+ import figma from '@figma/code-connect'
487
+ import * as RadioGroup from './RadioGroup'
488
+
489
+ figma.connect(RadioGroup.Root, 'https://www.figma.com/design/ua4LYtQHXt2lhHlCsSpdBm', {
490
+ props: {
491
+ colorPalette: figma.enum('Color Palette', {
492
+ Primary: 'primary', Secondary: 'secondary', Tertiary: 'tertiary',
493
+ Neutral: 'neutral', Error: 'error',
494
+ }),
495
+ },
496
+ example: ({ colorPalette }) => (
497
+ <RadioGroup.Root colorPalette={colorPalette}>
498
+ <RadioGroup.Item value="option">
499
+ <RadioGroup.ItemControl />
500
+ <RadioGroup.ItemText>Option</RadioGroup.ItemText>
501
+ <RadioGroup.ItemHiddenInput />
502
+ </RadioGroup.Item>
503
+ </RadioGroup.Root>
504
+ ),
505
+ })
506
+ ```
507
+
508
+ #### `src/components/Avatar.figma.tsx`
509
+ ```tsx
510
+ import figma from '@figma/code-connect'
511
+ import * as Avatar from './Avatar'
512
+
513
+ figma.connect(Avatar.Root, 'https://www.figma.com/design/ua4LYtQHXt2lhHlCsSpdBm', {
514
+ props: {
515
+ size: figma.enum('Size', { xs: 'xs', sm: 'sm', md: 'md', lg: 'lg', xl: 'xl', '2xl': '2xl' }),
516
+ },
517
+ example: ({ size }) => (
518
+ <Avatar.Root size={size}>
519
+ <Avatar.Image src="avatar.jpg" alt="User" />
520
+ <Avatar.Fallback name="User Name" />
521
+ </Avatar.Root>
522
+ ),
523
+ })
524
+ ```
525
+
526
+ #### `src/components/Progress.figma.tsx`
527
+ ```tsx
528
+ import figma from '@figma/code-connect'
529
+ import * as Progress from './Progress'
530
+
531
+ figma.connect(Progress.Root, 'https://www.figma.com/design/ua4LYtQHXt2lhHlCsSpdBm', {
532
+ props: {
533
+ colorPalette: figma.enum('Color Palette', {
534
+ Primary: 'primary', Secondary: 'secondary', Tertiary: 'tertiary', Error: 'error',
535
+ }),
536
+ },
537
+ example: ({ colorPalette }) => (
538
+ <Progress.Root value={50} colorPalette={colorPalette}>
539
+ <Progress.Label>Label</Progress.Label>
540
+ <Progress.ValueText />
541
+ <Progress.Track><Progress.Range /></Progress.Track>
542
+ </Progress.Root>
543
+ ),
544
+ })
545
+ ```
546
+
547
+ #### `src/components/Tooltip.figma.tsx`
548
+ ```tsx
549
+ import figma from '@figma/code-connect'
550
+ import * as Tooltip from './Tooltip'
551
+
552
+ figma.connect(Tooltip.Tooltip, 'https://www.figma.com/design/ua4LYtQHXt2lhHlCsSpdBm', {
553
+ props: {
554
+ content: figma.string('Content'),
555
+ },
556
+ example: ({ content }) => (
557
+ <Tooltip.Tooltip content={content} showArrow>
558
+ <button>Trigger</button>
559
+ </Tooltip.Tooltip>
560
+ ),
561
+ })
562
+ ```
563
+
564
+ #### `src/components/Popover.figma.tsx`
565
+ ```tsx
566
+ import figma from '@figma/code-connect'
567
+ import * as Popover from './Popover'
568
+
569
+ figma.connect(Popover.Root, 'https://www.figma.com/design/ua4LYtQHXt2lhHlCsSpdBm', {
570
+ example: () => (
571
+ <Popover.Root>
572
+ <Popover.Trigger asChild><button>Trigger</button></Popover.Trigger>
573
+ <Popover.Positioner>
574
+ <Popover.Content>
575
+ <Popover.Arrow><Popover.ArrowTip /></Popover.Arrow>
576
+ <Popover.Title>Title</Popover.Title>
577
+ <Popover.Description>Description</Popover.Description>
578
+ </Popover.Content>
579
+ </Popover.Positioner>
580
+ </Popover.Root>
581
+ ),
582
+ })
583
+ ```
584
+
585
+ #### `src/components/Breadcrumb.figma.tsx`
586
+ ```tsx
587
+ import figma from '@figma/code-connect'
588
+ import * as Breadcrumb from './Breadcrumb'
589
+
590
+ figma.connect(Breadcrumb.Root, 'https://www.figma.com/design/ua4LYtQHXt2lhHlCsSpdBm', {
591
+ example: () => (
592
+ <Breadcrumb.Root>
593
+ <Breadcrumb.List>
594
+ <Breadcrumb.Item>
595
+ <Breadcrumb.Link href="#">Home</Breadcrumb.Link>
596
+ </Breadcrumb.Item>
597
+ <Breadcrumb.Separator />
598
+ <Breadcrumb.Item>
599
+ <Breadcrumb.CurrentLink>Current</Breadcrumb.CurrentLink>
600
+ </Breadcrumb.Item>
601
+ </Breadcrumb.List>
602
+ </Breadcrumb.Root>
603
+ ),
604
+ })
605
+ ```
606
+
607
+ #### `src/components/ContentCard/ContentCard.figma.tsx`
608
+ ```tsx
609
+ import figma from '@figma/code-connect'
610
+ import * as ContentCard from './index'
611
+
612
+ figma.connect(ContentCard.Root, 'https://www.figma.com/design/ua4LYtQHXt2lhHlCsSpdBm', {
613
+ props: {
614
+ variant: figma.enum('Variant', { Outline: 'outline', Elevated: 'elevated', Flat: 'flat' }),
615
+ size: figma.enum('Size', { sm: 'sm', md: 'md', lg: 'lg' }),
616
+ },
617
+ example: ({ variant, size }) => (
618
+ <ContentCard.Root variant={variant} size={size}>
619
+ <ContentCard.Header>
620
+ <ContentCard.Title>Title</ContentCard.Title>
621
+ <ContentCard.BadgeBar>badges</ContentCard.BadgeBar>
622
+ </ContentCard.Header>
623
+ <ContentCard.Body>Content</ContentCard.Body>
624
+ <ContentCard.Separator />
625
+ <ContentCard.Section>
626
+ <ContentCard.SectionTitle>Section</ContentCard.SectionTitle>
627
+ <ContentCard.List>
628
+ <ContentCard.ListItem>Item</ContentCard.ListItem>
629
+ </ContentCard.List>
630
+ </ContentCard.Section>
631
+ </ContentCard.Root>
632
+ ),
633
+ })
634
+ ```
635
+
636
+ #### `src/components/NavigationMenu/NavigationMenu.figma.tsx`
637
+ ```tsx
638
+ import figma from '@figma/code-connect'
639
+ import { NavigationMenu } from './index'
640
+
641
+ figma.connect(NavigationMenu, 'https://www.figma.com/design/ua4LYtQHXt2lhHlCsSpdBm', {
642
+ example: () => (
643
+ <NavigationMenu
644
+ sections={sections}
645
+ defaultOpenSections={['dashboard']}
646
+ activeHref="/dashboard/progress"
647
+ />
648
+ ),
649
+ })
650
+ ```
651
+
652
+ #### `src/components/ScenarioSettings/ScenarioSettings.figma.tsx`
653
+ ```tsx
654
+ import figma from '@figma/code-connect'
655
+ import { ScenarioSettings } from './index'
656
+
657
+ figma.connect(ScenarioSettings, 'https://www.figma.com/design/ua4LYtQHXt2lhHlCsSpdBm', {
658
+ example: () => (
659
+ <ScenarioSettings
660
+ defaultValue={['duration', 'number-of-questions']}
661
+ defaultDuration="standard"
662
+ defaultQuestionCount="standard"
663
+ />
664
+ ),
665
+ })
666
+ ```
667
+
668
+ #### `src/components/ScenarioQueue/ScenarioQueue.figma.tsx`
669
+ ```tsx
670
+ import figma from '@figma/code-connect'
671
+ import { ScenarioQueue } from './index'
672
+
673
+ figma.connect(ScenarioQueue, 'https://www.figma.com/design/ua4LYtQHXt2lhHlCsSpdBm', {
674
+ example: () => (
675
+ <ScenarioQueue
676
+ scenarios={scenarios}
677
+ onReorder={handleReorder}
678
+ onRequeue={handleRequeue}
679
+ />
680
+ ),
681
+ })
682
+ ```
683
+
684
+ #### `src/components/Stepper/Stepper.figma.tsx`
685
+ ```tsx
686
+ import figma from '@figma/code-connect'
687
+ import { Stepper } from './index'
688
+
689
+ figma.connect(Stepper, 'https://www.figma.com/design/ua4LYtQHXt2lhHlCsSpdBm', {
690
+ props: {
691
+ colorPalette: figma.enum('Color Palette', { Primary: 'primary', Secondary: 'secondary' }),
692
+ },
693
+ example: ({ colorPalette }) => (
694
+ <Stepper
695
+ steps={steps}
696
+ defaultStep={0}
697
+ colorPalette={colorPalette}
698
+ showContent
699
+ showActions
700
+ />
701
+ ),
702
+ })
703
+ ```
704
+
705
+ #### `src/components/Skeleton.figma.tsx`
706
+ ```tsx
707
+ import figma from '@figma/code-connect'
708
+ import * as Skeleton from './Skeleton'
709
+
710
+ figma.connect(Skeleton.Skeleton, 'https://www.figma.com/design/ua4LYtQHXt2lhHlCsSpdBm', {
711
+ example: () => <Skeleton.Skeleton css={{ h: '4', w: '40', borderRadius: 'md' }} />,
712
+ })
713
+ ```
714
+
715
+ ### 3D. Add npm scripts to package.json
716
+
717
+ Add these two scripts:
718
+
719
+ ```json
720
+ "figma:connect": "figma connect publish",
721
+ "figma:connect:dry": "figma connect publish --dry-run"
722
+ ```
723
+
724
+ ### 3E. Ensure .env is gitignored
725
+
726
+ ```bash
727
+ grep -q "^\.env$" .gitignore || echo ".env" >> .gitignore
728
+ grep -q "^\.env\.local$" .gitignore || echo ".env.local" >> .gitignore
729
+ ```
730
+
731
+ ### 3F. Create `.env.example`
732
+
733
+ ```
734
+ FIGMA_ACCESS_TOKEN=your-figma-personal-access-token
735
+ ```
736
+
737
+ ### 3G. Verify Phase 3
738
+
739
+ Run the dry-run to check annotations parse:
740
+
741
+ ```bash
742
+ source .env
743
+ pnpm figma:connect:dry 2>&1 | head -50
744
+ ```
745
+
746
+ This will likely warn about unresolved Figma node URLs (expected — the components don't exist as Figma components yet), but it should NOT show syntax errors. If there are syntax errors in any `.figma.tsx` file, fix them and re-run.
747
+
748
+ ---
749
+
750
+ ## Execution Rules — READ THESE
751
+
752
+ 1. **Do NOT stop to ask me anything.** Make reasonable decisions and proceed.
753
+ 2. **Do NOT ask "should I proceed to Phase 3?" or "would you like me to continue?"** — just do it.
754
+ 3. **If a phase fails**, fix the issue and retry (up to 3 attempts per step).
755
+ 4. **If Storybook isn't running**, start it.
756
+ 5. **If Figma MCP write tools are not available**, document what IS available, save screenshots to `docs/figma-captures/`, and move on to Phase 3.
757
+ 6. **If Code Connect dry-run shows syntax errors**, fix them. If it shows warnings about unresolved URLs, that's expected — move on.
758
+ 7. **At the very end**, provide a single summary of what succeeded and what needs manual attention. Format it as a table like:
759
+
760
+ ```
761
+ | Phase | Status | Notes |
762
+ |-------|--------|-------|
763
+ | Phase 2 | ✅/❌ | ... |
764
+ | Phase 3 | ✅/❌ | ... |
765
+ ```