@motion-proto/live-tokens 0.73.0 → 0.75.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (196) hide show
  1. package/.claude/skills/live-tokens-check-compliance/SKILL.md +33 -38
  2. package/.claude/skills/live-tokens-create-component/SKILL copy.md +196 -0
  3. package/.claude/skills/live-tokens-create-component/SKILL.md +198 -146
  4. package/.claude/skills/live-tokens-create-component/references/contract-tests.md +95 -52
  5. package/.claude/skills/live-tokens-create-component/references/intrinsics.md +2 -2
  6. package/.claude/skills/live-tokens-create-component/references/linked-siblings.md +2 -2
  7. package/.claude/skills/live-tokens-create-component/references/sketch-mode.md +12 -12
  8. package/.claude/skills/live-tokens-create-component/references/token-naming.md +2 -1
  9. package/.claude/skills/live-tokens-create-page/SKILL.md +187 -0
  10. package/.claude/skills/live-tokens-create-page/references/interaction-sources.md +66 -0
  11. package/.claude/skills/live-tokens-create-page/references/layout-sources.md +87 -0
  12. package/.claude/skills/live-tokens-create-theme/SKILL.md +84 -0
  13. package/.claude/skills/live-tokens-create-theme/references/design-directions.md +94 -0
  14. package/.claude/skills/live-tokens-fix-findings/SKILL.md +69 -60
  15. package/.claude/skills/live-tokens-pick-component/SKILL.md +64 -79
  16. package/.claude/skills/live-tokens-set-colors/SKILL.md +149 -0
  17. package/.claude/skills/live-tokens-set-colors/references/color-anchors.md +80 -0
  18. package/.claude/skills/live-tokens-set-geometry/SKILL.md +121 -0
  19. package/.claude/skills/live-tokens-set-geometry/references/geometry-anchors.md +63 -0
  20. package/.claude/skills/live-tokens-set-type/SKILL.md +93 -0
  21. package/.claude/skills/live-tokens-set-type/references/type-anchors.md +60 -0
  22. package/CHANGELOG.md +194 -0
  23. package/README.md +27 -18
  24. package/bin/check-component.mjs +91 -19
  25. package/bin/check-page.mjs +105 -24
  26. package/bin/cli.mjs +154 -97
  27. package/bin/contractRunner.mjs +945 -0
  28. package/bin/create.mjs +1 -1
  29. package/bin/lib/catalogue.mjs +37 -30
  30. package/bin/lib/findings.mjs +46 -15
  31. package/bin/lib/liveState.mjs +110 -0
  32. package/bin/lib/report.mjs +3 -3
  33. package/bin/lib/tokenVocabulary.mjs +4 -4
  34. package/bin/migrate-routes.mjs +5 -5
  35. package/bin/migrate.mjs +4 -4
  36. package/bin/save-theme.mjs +176 -0
  37. package/bin/set-colors.mjs +189 -0
  38. package/bin/{adjust.mjs → set-geometry.mjs} +25 -57
  39. package/bin/{set-fonts.mjs → set-type.mjs} +26 -62
  40. package/dist-plugin/{chunk-W6Y4BWFB.js → chunk-6WGFOJXO.js} +22 -0
  41. package/dist-plugin/{chunk-RIXO2E55.js → chunk-PDNL4NC5.js} +9 -2
  42. package/dist-plugin/{chunk-YLCOIGQC.js → chunk-SWXRVZKT.js} +98 -2
  43. package/dist-plugin/{dataPaths-BhWzd5cL.d.ts → dataPaths-BpIK_Obx.d.cts} +1 -0
  44. package/dist-plugin/{dataPaths-BhWzd5cL.d.cts → dataPaths-BpIK_Obx.d.ts} +1 -0
  45. package/dist-plugin/index.cjs +366 -148
  46. package/dist-plugin/index.d.cts +1 -1
  47. package/dist-plugin/index.d.ts +1 -1
  48. package/dist-plugin/index.js +226 -130
  49. package/dist-plugin/migrateData/index.cjs +121 -2
  50. package/dist-plugin/migrateData/index.d.cts +1 -1
  51. package/dist-plugin/migrateData/index.d.ts +1 -1
  52. package/dist-plugin/migrateData/index.js +3 -3
  53. package/dist-plugin/{generateColorsAndType → setColors}/index.cjs +594 -499
  54. package/dist-plugin/{generateColorsAndType → setColors}/index.d.cts +34 -25
  55. package/dist-plugin/{generateColorsAndType → setColors}/index.d.ts +34 -25
  56. package/dist-plugin/{generateColorsAndType → setColors}/index.js +48 -66
  57. package/dist-plugin/{adjust → setGeometry}/index.cjs +166 -48
  58. package/dist-plugin/{adjust → setGeometry}/index.d.cts +6 -6
  59. package/dist-plugin/{adjust → setGeometry}/index.d.ts +6 -6
  60. package/dist-plugin/{adjust → setGeometry}/index.js +51 -45
  61. package/dist-plugin/{fontPairing → setType}/index.cjs +19 -4
  62. package/dist-plugin/{fontPairing → setType}/index.d.cts +2 -2
  63. package/dist-plugin/{fontPairing → setType}/index.d.ts +2 -2
  64. package/dist-plugin/{fontPairing → setType}/index.js +1 -1
  65. package/dist-plugin/{themeTypes-DSV3Zisf.d.cts → themeTypes-BxRtuN5V.d.cts} +1 -1
  66. package/dist-plugin/{themeTypes-DSV3Zisf.d.ts → themeTypes-BxRtuN5V.d.ts} +1 -1
  67. package/dist-plugin/tokensCssMigrations/index.d.cts +1 -1
  68. package/dist-plugin/tokensCssMigrations/index.d.ts +1 -1
  69. package/dist-plugin/tokensCssMigrations/index.js +1 -1
  70. package/package.json +36 -8
  71. package/src/app/site.css +19 -9
  72. package/src/editor/bootstrap.ts +2 -0
  73. package/src/editor/component-editor/CollapsibleSectionEditor.svelte +4 -4
  74. package/src/editor/component-editor/DialogEditor.svelte +4 -4
  75. package/src/editor/component-editor/MenuSelectEditor.svelte +4 -1
  76. package/src/editor/component-editor/SegmentedControlEditor.svelte +6 -1
  77. package/src/editor/component-editor/TabBarEditor.svelte +1 -1
  78. package/src/editor/component-editor/TableEditor.svelte +2 -2
  79. package/src/editor/component-editor/scaffolding/TokenLayout.svelte +6 -3
  80. package/src/editor/component-editor/scaffolding/VariantGroup.svelte +41 -20
  81. package/src/editor/core/components/adjustAliases.ts +59 -45
  82. package/src/editor/core/components/aliasKinds.ts +9 -5
  83. package/src/editor/core/preview/themePreview.ts +9 -2
  84. package/src/editor/core/sketch/sketchLayer.ts +22 -0
  85. package/src/editor/core/store/editorStore.ts +10 -1
  86. package/src/editor/core/themes/{generateColorsAndType.ts → buildColors.ts} +84 -98
  87. package/src/editor/core/themes/liveStateStream.ts +26 -0
  88. package/src/editor/core/themes/migrations/2026-09-03-drop-legacy-component-keys.ts +62 -0
  89. package/src/editor/core/themes/migrations/2026-09-07-stroke-role-renames.ts +52 -0
  90. package/src/editor/core/themes/migrations/index.ts +4 -0
  91. package/src/editor/core/themes/themeDocumentSync.ts +22 -11
  92. package/src/editor/core/themes/themeService.ts +9 -2
  93. package/src/editor/docs/content/themes-workflow.md +2 -2
  94. package/src/editor/docs/content.generated.ts +1 -1
  95. package/src/editor/overlay/LiveEditorOverlay.svelte +519 -28
  96. package/src/editor/pages/ComponentEditorPage.svelte +17 -1
  97. package/src/editor/pages/liveTokensEditorHandle.ts +23 -0
  98. package/src/editor/skill-atlas/SkillAtlas.svelte +76 -574
  99. package/src/editor/skill-atlas/TreeCanvas.svelte +263 -0
  100. package/src/editor/skill-atlas/TreeNodeCard.svelte +136 -53
  101. package/src/editor/skill-atlas/edges.ts +31 -0
  102. package/src/editor/skill-atlas/skillSources.generated.ts +29 -24
  103. package/src/editor/skill-atlas/skillTrees.ts +19 -3687
  104. package/src/editor/skill-atlas/trees/check-compliance.ts +183 -0
  105. package/src/editor/skill-atlas/trees/create-component.ts +275 -0
  106. package/src/editor/skill-atlas/trees/create-page.ts +320 -0
  107. package/src/editor/skill-atlas/trees/create-theme.ts +255 -0
  108. package/src/editor/skill-atlas/trees/fix-findings.ts +469 -0
  109. package/src/editor/skill-atlas/trees/pick-component.ts +300 -0
  110. package/src/editor/skill-atlas/trees/set-colors.ts +148 -0
  111. package/src/editor/skill-atlas/trees/set-geometry.ts +136 -0
  112. package/src/editor/skill-atlas/trees/set-type.ts +142 -0
  113. package/src/editor/skill-atlas/types.ts +3 -4
  114. package/src/editor/skill-atlas/wireLayout.ts +287 -0
  115. package/src/live-tokens/data/colors-and-type/autumn.json +1 -37
  116. package/src/live-tokens/data/colors-and-type/default.json +1 -37
  117. package/src/live-tokens/data/colors-and-type/halloween.json +1 -37
  118. package/src/live-tokens/data/colors-and-type/midnight-study.json +1 -37
  119. package/src/live-tokens/data/colors-and-type/ocean.json +1 -37
  120. package/src/live-tokens/data/colors-and-type/royal-velvet.json +1 -37
  121. package/src/live-tokens/data/colors-and-type/sketchy.json +1 -37
  122. package/src/live-tokens/data/colors-and-type/spring-meadow.json +1 -37
  123. package/src/live-tokens/data/colors-and-type/sunset.json +1 -37
  124. package/src/live-tokens/data/themes/autumn.json +16 -52
  125. package/src/live-tokens/data/themes/halloween.json +16 -52
  126. package/src/live-tokens/data/themes/midnight-study.json +16 -52
  127. package/src/live-tokens/data/themes/ocean.json +16 -52
  128. package/src/live-tokens/data/themes/royal-velvet.json +16 -52
  129. package/src/live-tokens/data/themes/sketchy.json +16 -52
  130. package/src/live-tokens/data/themes/spring-meadow.json +16 -52
  131. package/src/live-tokens/data/themes/sunset.json +16 -52
  132. package/src/live-tokens/data/tokens.generated.css +0 -36
  133. package/src/system/components/Badge.svelte +7 -0
  134. package/src/system/components/Button.svelte +7 -0
  135. package/src/system/components/Callout.svelte +10 -6
  136. package/src/system/components/Card.svelte +23 -4
  137. package/src/system/components/CodeSnippet.svelte +4 -3
  138. package/src/system/components/CollapsibleSection.svelte +23 -8
  139. package/src/system/components/CornerBadge.svelte +6 -0
  140. package/src/system/components/Dialog.svelte +13 -6
  141. package/src/system/components/IconButton.svelte +9 -0
  142. package/src/system/components/Image.svelte +8 -0
  143. package/src/system/components/ImageLightbox.svelte +6 -0
  144. package/src/system/components/InlineEditActions.svelte +7 -0
  145. package/src/system/components/Input.svelte +7 -0
  146. package/src/system/components/MenuSelect.svelte +7 -0
  147. package/src/system/components/Notification.svelte +7 -0
  148. package/src/system/components/Panel.svelte +6 -0
  149. package/src/system/components/ProgressBar.svelte +5 -0
  150. package/src/system/components/RadioButton.svelte +11 -5
  151. package/src/system/components/SectionDivider.svelte +8 -0
  152. package/src/system/components/SegmentedControl.svelte +6 -0
  153. package/src/system/components/SideNavigation.svelte +6 -0
  154. package/src/system/components/Slider.svelte +7 -4
  155. package/src/system/components/TabBar.svelte +15 -9
  156. package/src/system/components/Table.svelte +8 -3
  157. package/src/system/components/Toggle.svelte +4 -4
  158. package/src/system/components/Tooltip.svelte +6 -0
  159. package/src/testing-js/chunk-AO7EZHYV.js +776 -0
  160. package/src/testing-js/chunk-AO7EZHYV.js.map +1 -0
  161. package/src/testing-js/chunk-FAFOAWYL.js +39 -0
  162. package/src/testing-js/chunk-FAFOAWYL.js.map +1 -0
  163. package/src/testing-js/chunk-L73N4NSO.js +23 -0
  164. package/src/testing-js/chunk-L73N4NSO.js.map +1 -0
  165. package/src/testing-js/chunk-LXR3MN6N.js +3063 -0
  166. package/src/testing-js/chunk-LXR3MN6N.js.map +1 -0
  167. package/src/testing-js/chunk-ZMSX6CXR.js +53 -0
  168. package/src/testing-js/chunk-ZMSX6CXR.js.map +1 -0
  169. package/src/testing-js/component-alias.contract.js +81 -0
  170. package/src/testing-js/component-alias.contract.js.map +1 -0
  171. package/src/testing-js/component-editor.contract.js +62 -0
  172. package/src/testing-js/component-editor.contract.js.map +1 -0
  173. package/src/testing-js/component-render.contract.js +568 -0
  174. package/src/testing-js/component-render.contract.js.map +1 -0
  175. package/src/testing-js/index.d.ts +293 -0
  176. package/src/testing-js/index.js +222 -0
  177. package/src/testing-js/index.js.map +1 -0
  178. package/src/testing-js/registry.contract.js +39 -0
  179. package/src/testing-js/registry.contract.js.map +1 -0
  180. package/src/testing-js/vitest-BE6uGF31.d.ts +73 -0
  181. package/src/testing-js/vitest.d.ts +3 -0
  182. package/src/testing-js/vitest.js +13 -0
  183. package/src/testing-js/vitest.js.map +1 -0
  184. package/template/README.md +13 -0
  185. package/template/_gitignore +2 -0
  186. package/template/package.json +2 -1
  187. package/template/src/pages/Home.svelte +4 -18
  188. package/.claude/skills/live-tokens-adjust-geometry/SKILL.md +0 -93
  189. package/.claude/skills/live-tokens-build-page/SKILL.md +0 -103
  190. package/.claude/skills/live-tokens-build-page/references/layout-sources.md +0 -48
  191. package/.claude/skills/live-tokens-generate-theme/SKILL.md +0 -156
  192. package/.claude/skills/live-tokens-generate-theme/references/mood-vocabulary.md +0 -43
  193. package/.claude/skills/live-tokens-generate-theme/references/named-themes.md +0 -18
  194. package/.claude/skills/live-tokens-generate-theme/references/style-vocabulary.md +0 -35
  195. package/.claude/skills/live-tokens-pair-fonts/SKILL.md +0 -90
  196. package/bin/generate-theme.mjs +0 -260
@@ -0,0 +1,94 @@
1
+ # Design directions: feelings, idioms, and occasions
2
+
3
+ Read this once the request names a feeling, a design idiom, an era, a genre, a
4
+ holiday, a season, or a natural scene. Each entry places the request and gives
5
+ the direction the three intents come from.
6
+
7
+ The mechanics live with the executors. Color anchors are in
8
+ live-tokens-set-colors, type anchors in live-tokens-set-type, geometry anchors
9
+ in live-tokens-set-geometry, each keyed on the same names as the tables below.
10
+ Name the anchor in the intent, and the sibling reads its own column.
11
+
12
+ Three axes place any request, including one no entry lists:
13
+
14
+ | Axis | Reads as | Carried by |
15
+ |---|---|---|
16
+ | Valence | pleasant against unpleasant | lightness, above everything else |
17
+ | Energy | aroused against calm | chroma, and hue distance on screen |
18
+ | Dominance | assertive against yielding | surface contrast, type weight, border weight, tightness |
19
+
20
+ An idiom sets constraints and a feeling moves dials, so a request that names
21
+ both ("cozy brutalist", "clinical Swiss") reads the idiom first and lets the
22
+ feeling move the dials inside it.
23
+
24
+ ## Feelings
25
+
26
+ Valence and energy set the quadrant, and the table runs in quadrant order:
27
+ pleasant-aroused, pleasant-calm, unpleasant-aroused, unpleasant-calm. Dominance
28
+ separates confident from gentle inside one quadrant and lives almost entirely
29
+ outside color.
30
+
31
+ | Request | Placement | Direction |
32
+ |---|---|---|
33
+ | Joyful, exuberant, energetic | pleasant, high energy | warm and bright throughout, with nothing held back |
34
+ | Playful, whimsical | pleasant, high energy, low dominance | four hue families at play, soft and generous |
35
+ | Optimistic, hopeful | pleasant, moderate energy | a cool ground lit by one warm counterpoint, like sunrise |
36
+ | Confident, bold | pleasant, high energy, high dominance | wide contrast, heavy weight, held tight |
37
+ | Serene, tranquil | pleasant, low energy | cool and quiet, with nothing loud anywhere |
38
+ | Tender, gentle, romantic | pleasant, low energy, low dominance | a soft warm ground, a narrow range, light weights |
39
+ | Cozy, comforting | pleasant, low energy | warm through and through, nothing cool on screen |
40
+ | Wistful, nostalgic, vintage, faded | pleasant, low energy | chroma withheld rather than light withheld |
41
+ | Earthy, grounded, natural | pleasant, low energy, moderate dominance | warm mineral hues, nothing synthetic |
42
+ | Clinical, sterile, precise | neutral, low energy, high dominance | an untinted ground, one cool hue, tightly set |
43
+ | Contemplative, focused | neutral, low energy | one cool hue and almost nothing else |
44
+ | Urgent, alarming | unpleasant, high energy, high dominance | a neutral ground so the alarm lands, heavy and tight |
45
+ | Tense, anxious | unpleasant, high energy | an uncomfortable ground under a pair that vibrates |
46
+ | Defiant, rebellious, loud | unpleasant, high energy, highest dominance | near-black under one acid hue, blunt everywhere |
47
+ | Melancholy, moody, sad | unpleasant, low energy | dark and cool, holding one moment of color |
48
+ | Somber, grave, mournful | unpleasant, low energy, high dominance | near-neutral dark, sharp and quiet |
49
+ | Ominous, dramatic, haunted | unpleasant, low energy, high dominance | dark with one hot accent and real atmosphere |
50
+ | Austere, severe, cold | unpleasant, lowest energy, highest dominance | monochrome at one extreme of lightness |
51
+
52
+ ## Idioms, eras, and genres
53
+
54
+ The table runs modernist, digital, quiet, print, expressive.
55
+
56
+ | Request | Placement | Direction |
57
+ |---|---|---|
58
+ | Swiss, International | neutral, low energy, high dominance | one hue on a near-white ground, rational, tight |
59
+ | Bauhaus | pleasant, high energy, high dominance | primaries at full commitment on paper, geometric, square but for the circle |
60
+ | Mid-century modern | pleasant, moderate energy | warm muted mid-tones, soft and open, no borders |
61
+ | Art deco, opulent, luxurious | pleasant, low energy, high dominance | dark with one metal, high-contrast type, sharp |
62
+ | Terminal, phosphor | neutral, moderate energy, high dominance | one phosphor hue on near-black, mono, bordered |
63
+ | Cyberpunk, neon noir, futuristic | unpleasant, high energy, high dominance | dark with two neons and a glow, wide type, sharp |
64
+ | Vaporwave | pleasant, moderate energy, low dominance | light sunset pastels with a gradient, retro display, soft |
65
+ | Y2K, bubble | pleasant, high energy | a chrome ground under electric color, geometric, pills |
66
+ | Blueprint | neutral, low energy, high dominance | a drafting ground with pale rules, technical type, gridded |
67
+ | Scandinavian, hygge | pleasant, low energy, low dominance | a chalk ground and muted naturals, soft and open |
68
+ | Japandi, wabi-sabi | pleasant, lowest energy | unbleached paper, near-monochrome, generous space, no borders |
69
+ | Cottagecore, botanical | pleasant, low energy, low dominance | warm cream and garden hues, serif display, soft |
70
+ | Editorial, magazine | neutral, low energy, high dominance | paper and ink with one strong hue, carried by rules |
71
+ | Newsprint, broadsheet | neutral, low energy | grey-warm paper under near-black ink, serif throughout, tight |
72
+ | Risograph, zine | pleasant, high energy, high dominance | two flat spot inks on paper, expressive display, heavy rules |
73
+ | Corporate, professional, trustworthy | pleasant, low energy | cool near-white with navy and teal, conventional everywhere |
74
+ | Brutalist | unpleasant, high energy, highest dominance | a pure ground, one alarming hue, heavy type, thick borders |
75
+ | Memphis, postmodern | pleasant, highest energy | a pastel ground under four hue families, shapes set against each other |
76
+ | Industrial, workshop, gritty | neutral, moderate energy, high dominance | concrete and steel with safety orange, condensed type, thick borders |
77
+
78
+ ## Occasions
79
+
80
+ An occasion fixes color only, so its type and geometry intents come from the
81
+ feeling it implies or from the generic tables in the sibling skills.
82
+
83
+ Every occasion is a statement request: the named color goes on the ground
84
+ rather than only on the buttons.
85
+
86
+ | Request | Direction |
87
+ |---|---|
88
+ | Christmas | red and green with gold, one of the two owning the ground |
89
+ | Halloween | pumpkin, violet, and poison green, dark either way |
90
+ | St. Patrick's | green with gold over a pale ground |
91
+ | Ocean | blues held to one narrow band |
92
+ | Sunset | a hue sweep through red, falling in lightness |
93
+ | Autumn | parchment under rust, gold, and moss |
94
+ | Spring | pastels, greens and pinks over a mint ground |
@@ -1,89 +1,98 @@
1
1
  ---
2
2
  name: live-tokens-fix-findings
3
- description: Bring an existing @motion-proto/live-tokens project into line with its design system by running check-page and check-component, reading the findings, and fixing each by rule until both exit 0. Use when the user asks to make the build pass, fix the design-system errors or warnings, clean up the literals, replace hex or pixel values with tokens, make a page or component themeable, or apply what a check reported. Not for the check itself (live-tokens-check-compliance reports and edits nothing), not for building a new page (live-tokens-build-page) or a new component (live-tokens-create-component), which run the same gate as their last step, and not for a single token edit (use the editor).
3
+ description: Fix every finding of check-page and check-component in an existing @motion-proto/live-tokens project until both exit 0. Called with the fix list by live-tokens-check-compliance. Use when the user asks to fix the project. Edits the files the checkers name. Updates tokens.css only through the migration command.
4
4
  ---
5
5
 
6
- # Fixing the checkers' findings
6
+ # Fixing the findings of check-page and check-component
7
7
 
8
- Two checkers hold a project to its design system. `check-page` holds pages: every component comes from the catalogue and is passed only the props it declares, and every value in page CSS is a theme token. `check-component` holds authored components: every token names a semantic property and its default is the theme token that property reads. A page or component that passes repaints when the theme changes. One that fails has opted out of the system silently, and its findings say where.
9
-
10
- This skill is the loop for code that already exists. When the user has not seen the state of the project yet, **live-tokens-check-compliance** presents `npx live-tokens report` without editing; this skill edits.
8
+ Fix every finding of `check-page` and `check-component` until both exit 0. `check-page` checks pages. Every component comes from the catalogue, every prop is declared, and every value in page CSS is a design token. `check-component` checks authored components. Every token names a semantic property, and its default is the design token that property reads. Update `tokens.css` only through the migration command. That command also heals the data tree, and with `--write` rewrites the route references it lists. When live-tokens-check-compliance hands over a fix list, the user's choices in it stand.
11
9
 
12
10
  ## Workflow
13
11
 
14
- 1. Run both checkers with `--json`. Each finding carries a stable `rule`, a file, and a line.
12
+ When `check-page` is an unknown command, upgrade `@motion-proto/live-tokens` first.
13
+
14
+ 1. Run `npx live-tokens migrate --check` to see the plan, then `npx live-tokens migrate` to apply it. `--tokens <path>` names a tokens.css in an unusual place.
15
+ 2. Run both checkers with `--json`. Each finding carries a `rule`, a file, and a line.
15
16
  ```sh
16
- npx live-tokens check-page --json # every page under src/
17
- npx live-tokens check-component --json # every component authored under src/system/components
17
+ npx live-tokens check-page --json
18
+ npx live-tokens check-component --json
18
19
  ```
19
- `check-page src/pages/Home.svelte` and `check-component <id>` scope a run when the user names one thing. Unknown command means the installed package predates the checkers: upgrade `@motion-proto/live-tokens`, then run `npx live-tokens migrate --check` and apply what it plans with `--write` (`--tokens <path>` for a tokens.css outside the four default locations).
20
- 2. Group by rule. Take errors before warnings, and the rule with the most findings first, because one recipe clears the whole group.
21
- 3. Apply that rule's recipe to every finding in the group: colour by role, geometry by scale, or the row in the table below. A component outside the catalogue hands off to **live-tokens-pick-component** for the shipped one that fits, or to **live-tokens-create-component**.
22
- 4. Run again. New findings can appear as old ones clear: a token you reached for may not exist, or a moved import may land where a rule now sees it. Stop at exit 0.
23
- 5. Run once with `--strict` and report what it adds, so the user can decide whether warnings are worth clearing now. Then report by rule.
20
+ 3. Group the findings by rule.
21
+ 4. Take the largest error group first, then the remaining errors. Take warnings only when the repair scope includes warnings.
22
+ 5. Fix every finding in the group with its section: Color by role, Geometry by scale, or The remaining rules.
23
+ 6. Run both checkers again. When repairable findings remain in scope, return to step 3. When no token fits a remaining finding, leave it and continue to the reply with its reason.
24
+ 7. When the errors are clear, run both checkers with `--strict`. Report what `--strict` adds. Clear warnings within the existing request. Otherwise ask whether to clear the warnings now.
25
+ 8. When the repair scope includes warnings, return to step 3 with `--strict`. When strict checks pass or the user defers warnings, continue to the reply.
26
+ 9. Reply with:
27
+ - the changes by rule, each with its count and any visible shift
28
+ - the findings left, each with its reason and any config entry the user chose
29
+ - both checker commands with their exit codes
30
+
31
+ `check-page <path>` scopes a run to one page. `check-component <id>` scopes a run to one component: its runtime, its editor, and its registration. The checkers read tokens.css from its default location.
24
32
 
25
- A project scaffolded by `create` has a `check:design` script. Give any other project one in `package.json`, `"check:design": "live-tokens check-page && live-tokens check-component"`, and once it passes, gate the build: `"build": "npm run check:design && vite build"`.
33
+ When `package.json` has no `check:design` script, add `"check:design": "live-tokens check-page && live-tokens check-component"`. When both checkers exit 0, prepend `npm run check:design &&` to the existing build command. Preserve its other build steps.
26
34
 
27
- ## Three things the loop never does
35
+ ## Scope
28
36
 
29
- - **Silence a rule to pass.** `--off=<rule>` is for a single run while working. A severity the project wants changed goes in `live-tokens.config.json` under `"checks": { "rules": { "<rule>": "warn" } }`, with the reason in the commit, and only when the user has made that call.
30
- - **Mint a token.** A literal with no token behind it is remapped to the nearest existing token by role. No new `--surface-*`, `--text-*`, or `--space-*` is added to `tokens.css` to match a value the page happened to use. If nothing fits, say so and leave the finding.
31
- - **Change what the page looks like without saying so.** Most remaps land on the same value. When the nearest token differs, `14px` to `--space-16` or a 55% black to `--scrim`, name the shift in the report.
37
+ - Add no token to `tokens.css`. Map a literal with no matching token to the nearest existing token by role. When no token fits, leave the finding and say so.
38
+ - When the user has chosen to lower a rule's severity, record it in `live-tokens.config.json` under `"checks": { "rules": { "<rule>": "warn" } }`. `--off=<rule>` silences a rule for one run only.
39
+ - When the nearest token differs from the literal, use the token and name the shift in the report, such as `14px` to `--space-16`.
32
40
 
33
- ## Colour by role, never by hue
41
+ ## Color by role
34
42
 
35
- `color-literal` is the finding that takes judgement. The replacement is the token for what the colour *does*, not the token nearest in hue, because the theme moves every role together and the page must move with it. `npx live-tokens tokens --family surface` prints a family's names and values (`text`, `border`, `scrim`, `tint` likewise; `--json` for data); the families are fixed.
43
+ `color-literal` is a judgement finding. The replacement is the token for the role the color plays. The theme moves every role together. `npx live-tokens tokens --scale <name>` prints a scale's names and values, with `--json` for data.
36
44
 
37
- | The literal is | Token family | Notes |
45
+ | Literal | Token | Notes |
38
46
  | --- | --- | --- |
39
- | Text on a surface | `--text-primary`, `-secondary`, `-tertiary`, `-muted`, `-disabled` | The neutral scale. Family colour is `--text-accent`, `--text-success`, and so on. |
40
- | Light text on a dark chip over the page | `--text-inverted` | The one flip; no AA guarantee. |
41
- | A box's fill | `--surface-<family>-<level>` | `neutral` for chrome; `brand`, `accent`, `special` for emphasis; `info`, `success`, `warning`, `danger` for status. |
42
- | A stroke | `--border-<family>-<level>` | `faint`, `subtle`, base, `medium`, `strong` in the neutral family. |
43
- | A translucent layer that dims what is behind it | `--scrim-low`, `--scrim`, `--scrim-high` | Behind a modal, under a floating control. |
44
- | A translucent wash on a surface | `--tint-low`, `--tint`, `--tint-high` | Hover, an active tab, a code chip's background. |
45
- | Fully transparent | `--color-transparent` | Never `transparent` inside a component default. |
47
+ | Text on a surface | `--text-primary` through `--text-disabled` | The neutral text scale. `--text-<family>` for a family color. |
48
+ | Light text on a dark chip | `--text-inverted` | No AA guarantee. |
49
+ | A surface fill | `--surface-<family>-<level>` | The role names the family: `neutral` for chrome, `brand` for emphasis, `danger` for status. |
50
+ | A stroke | `--border-<family>-<level>` | Levels run `faint` to `strong`. |
51
+ | A translucent layer that dims what is behind it | `--scrim-low`, `--scrim`, `--scrim-high` | Behind a modal. |
52
+ | A translucent wash on a surface | `--tint-low`, `--tint`, `--tint-high` | A hover state. |
53
+ | Any other translucent color | The role's token at an opacity: `color-mix(in srgb, var(--surface-brand) 80%, transparent)` | The editor reads that form. |
54
+ | Fully transparent | `--color-transparent` | |
46
55
  | A gradient | `--gradient-*` | Or compose one from surface tokens. |
47
56
 
48
- A `var(--x, #fff)` fallback is not a finding. A named colour is: `white` and `rebeccapurple` are literals like any hex.
49
-
50
57
  ## Geometry by scale
51
58
 
52
- `dimension-literal` fires only on the geometry the theme owns: padding, margin, gap, border and outline widths, inset offsets, radius, and shadow. Sizing (a hero's height, a max content width, a `minmax()` floor) is layout and is never reported, so leave it.
59
+ `dimension-literal` is a mechanical finding. A size, such as a hero's height, is layout. Leave it.
53
60
 
54
- | The literal is | Token | Notes |
61
+ | Literal | Token | Notes |
55
62
  | --- | --- | --- |
56
- | Padding, margin, gap, an offset | `--space-<px>` | `npx live-tokens tokens --family space` prints the steps. Round to the nearest one and name the shift. |
63
+ | Spacing | `--space-<px>` | `npx live-tokens tokens --scale space` prints the steps. Round to the nearest step. |
57
64
  | A stroke width | `--border-width-1`, `-2`, `-4` | Also for `outline`. |
58
- | A corner | `--radius-sm` through `-4xl`, `--radius-full` | |
59
- | A shadow | `--shadow-sm` through `-xl` | Replace the whole value, never one offset. |
65
+ | A corner | `--radius-sm` through `--radius-4xl`, or `--radius-full` | |
66
+ | A shadow | `--shadow-sm` through `--shadow-xl` | Replace the whole value. |
60
67
  | Part of a `calc()` | The token inside the calc | `calc(var(--space-64) * -2 + var(--space-8))` |
68
+ | A duration or easing | `--duration-*`, `--ease-*` | No rule reports it. Fix it while in the file. |
69
+ | A `blur()` | `--blur-*` | No rule reports it. Fix it while in the file. |
61
70
 
62
- While in the file, motion values take `--duration-*` and `--ease-*` even though no rule reports them, and a `blur()` takes `--blur-*`.
63
-
64
- ## Every other rule
71
+ ## The remaining rules
65
72
 
66
73
  | Rule | Fix |
67
74
  | --- | --- |
68
- | `unknown-token` | A typo or a rename. Search `tokens.css` for the stem. A contract-family name (`--surface-…`, `--text-…`) that is gone was renamed: `npx live-tokens migrate --check` names the migration. |
69
- | `raw-text-axis` | Set the whole axis set from one text style: `--heading-xl` through `-sm`, `--body-md`, `--body-sm`, `--editorial-*`, `--eyebrow`, `--code`, each carrying `-font-family`, `-font-size`, `-font-weight`, `-line-height`, `-letter-spacing`. A `font:` shorthand is rewritten the same way. `em`, `%`, and a unitless line-height are relative and fine. |
70
- | `unknown-component` | Not in the catalogue. Read **live-tokens-pick-component** for the shipped one that fits, or author it with **live-tokens-create-component**. |
71
- | `unknown-prop` | The component drops it at runtime. `npx live-tokens components <id>` prints the props it declares and the values each union accepts; map the prop to one of them or delete it. A `class` on a component that declares none does nothing. |
72
- | `unknown-prop-value` | Pick a value from the union the message lists. |
73
- | `hardcoded-columns` | `repeat(var(--columns-count), 1fr)` for the page grid; `calc(var(--columns-count) - 2)` for a sub-grid spanning fewer page columns. A two-up or three-up is a layout and is not reported. |
74
- | `site-css-in-main` | Delete the import from `main.ts` and add it to each page's `<script>`, so page CSS never reaches the editor routes. |
75
- | `missing-source` | Add `source: 'src/...'` to the route entry so Page Source can open it. |
76
- | `reserved-route` | Move the route out of `/live-tokens/*`; the package owns that namespace. |
77
- | `deep-import` | Import from `@motion-proto/live-tokens` or `/component-editor` or `/components/<Name>.svelte`, never from `/src/`. |
78
- | `unknown-suffix`, `state-after-property`, `disabled-is-terminal` | Rename the token. Borrow the name a shipped component uses for the same role; the vocabulary and the state model are in **live-tokens-create-component**. |
79
- | `color-literal`, `unknown-token-ref`, `default-not-token` (component) | The `:global(:root)` default reads a theme token, composed if needed. A structural keyword (`start`, `contain`) is declared in the editor's `intrinsics`. |
80
- | `phantom-editor-token`, `phantom-link` | The editor names a token the runtime never declares, or a bare font helper spans slots. Both are editor fixes; see the same skill. |
81
- | `invalid-id`, `missing-file`, `missing-root-block`, `no-tokens`, `missing-component-const`, `missing-all-tokens`, `missing-registration` | The component is not wired the way the recipe in **live-tokens-create-component** wires it: a lowercase id, a runtime file with a `:global(:root)` block, an editor file exporting `component` and `allTokens`, and a `bootLiveTokens` entry. |
82
-
83
- ## Report
84
-
85
- Say what changed by rule, one line per rule with the count and any visible shift. Say what was left and why, with the config entry if the user chose to lower a severity. End with the two commands and their exit codes.
86
-
87
- ## Verify
88
-
89
- Open `/live-tokens/editor` in dev and change a surface colour and a spacing step. Every file the loop touched should repaint. One that does not still holds a literal the checker cannot see, which is worth reporting as a gap in the checker rather than patching around.
75
+ | `unknown-token` | Search `tokens.css` for the stem. When a contract-family name is gone, `npx live-tokens migrate --check` lists the migration that adds the current name. |
76
+ | `raw-text-axis` | Set every axis from one text style, `-font-family` through `-letter-spacing`. `npx live-tokens tokens --scale heading` prints one text style. The text styles are `heading`, `body`, `editorial`, and `code`. Rewrite a `font:` shorthand the same way. |
77
+ | `unknown-component` | Read **live-tokens-pick-component** for the shipped component that fits. When none fits, author one with **live-tokens-create-component**. |
78
+ | `unknown-prop` | `npx live-tokens components <id>` prints the declared props and their values. Map the prop to one of them, or delete it. |
79
+ | `unknown-prop-value` | Use a value from the union the message lists. |
80
+ | `control-size` | Delete the `size` prop. The shipped default is the page's size. When that default is wrong for the project, retune the component in `/live-tokens/components`. |
81
+ | `multiple-primary` | Keep the action that completes the main task `primary`. A Button with no `variant` counts as `primary`. Use `secondary` for supporting or related actions and `outline` for unrelated or informational actions. |
82
+ | `danger-without-dialog` | Open a `Dialog` from the danger Button or IconButton and run the action from the Dialog's confirm. The rule fires once per page, when the page imports no Dialog. For other actions, assign emphasis by the action's relationship to the main task. |
83
+ | `hardcoded-columns` | `repeat(var(--columns-count), 1fr)` for the page grid. `calc(var(--columns-count) - 2)` for a sub-grid spanning fewer columns. |
84
+ | `site-css-in-main` | Delete the import from `main.ts`. Add it to each page's `<script>`. Page CSS then stays off the editor routes. |
85
+ | `missing-source` | Add `source: 'src/...'` to the route entry. |
86
+ | `reserved-route` | Move the route out of `/live-tokens/*`. |
87
+ | `deep-import` | Import from `@motion-proto/live-tokens`, `/component-editor`, or `/components/<Name>.svelte`. |
88
+ | `fix: property-name` | Rename the token to the name a shipped component uses for the same role. The vocabulary and the state model are in **live-tokens-create-component**. |
89
+ | `fix: property-token` | Make the `:global(:root)` default read a design token, composed when needed. Declare a structural keyword, such as `start`, in the editor's `intrinsics`. |
90
+ | `fix: runtime` | Wire the component as the recipe in **live-tokens-create-component** wires it. |
91
+ | `fix: runtime-defaults` | Make the `:global(:root)` default the value Reset should restore, per the Runtime component section of **live-tokens-create-component**. |
92
+ | `fix: editor` | The editor names a token the runtime never declares, or a property targets the wrong part. Fix the editor's schema, states, or preview props by the Component editor section of **live-tokens-create-component**. |
93
+ | `fix: registration` | Register the component in the shared module the Registration section of **live-tokens-create-component** wires up, importable by the app and by `check-component --tests`. |
94
+ | `fix: sketch` | Add the missing Sketch part or marker, per the Sketch mode and overlays section of **live-tokens-create-component**. |
95
+ | `fix: tooling` | Install the named package (`@playwright/test`, `vitest`, or `happy-dom`) as a devDependency, then `npx playwright install chromium` for a missing browser. A bad path or config is named in the message; fix it and rerun `check-component <id> --tests`. |
96
+ | `fix: coverage` | A contract obligation never ran to a result. Add the missing contract, or find why the suite skipped it, then rerun. |
97
+
98
+ A `tests-*` finding names a problem with the run itself: the tool, the path, or a missing contract. Fix what the message names and rerun `check-component <id> --tests --json` until every applicable rule passes with no rule left `--off`.
@@ -1,111 +1,96 @@
1
1
  ---
2
2
  name: live-tokens-pick-component
3
- description: Recommend which shipped @motion-proto/live-tokens component fits a UX need, with decision trees for the confusable pairs (SegmentedControl / TabBar / RadioButton / MenuSelect, Card / CollapsibleSection / Dialog, Callout / Notification / Tooltip, and others). Use when the user asks which component to use, should I use X or Y, what is the difference between two components, how do I show / let the user / capture some UX outcome, or starts authoring a custom component before checking the catalogue. Read this before live-tokens-create-component. Not for placing the chosen component on a page (see live-tokens-build-page).
3
+ description: Recommend which shipped @motion-proto/live-tokens component fits a UX need, with a decision test for each confusable family. Called by live-tokens-create-page when more than one component could fit, and by live-tokens-create-component before it authors anything. Use when the user asks which component to use, or what the difference between two components is. Use when the user asks how to show or capture a UX outcome. Edits no file. For size, emphasis, or placement, read live-tokens-create-page. When the catalogue lacks a component with chrome, read live-tokens-create-component.
4
4
  ---
5
5
 
6
- # Picking the right live-tokens component
6
+ # Picking a live-tokens component
7
7
 
8
- This skill helps you choose between shipped components when several could plausibly fit. The catalogue is small; the hard part is semantic intent. A `RadioButton` set and a `SegmentedControl` can render identical-looking UIs but communicate different things.
9
-
10
- For composing a page once you've picked components, see **live-tokens-build-page**. For authoring a brand-new component when nothing fits, see **live-tokens-create-component** (but read this skill first to confirm nothing in the catalogue fits).
8
+ When more than one shipped component could fit, find the family below that names the candidates. Apply its test, which asks what the choice means to the reader.
11
9
 
12
10
  ## Catalogue
13
11
 
14
- Action: `Button`, `IconButton`, `InlineEditActions`. Input: `Input`, `Slider`. Selection: `SegmentedControl`, `TabBar`, `RadioButton`, `MenuSelect`, `Toggle`. Containers: `Card`, `CollapsibleSection`, `Dialog`, `Panel`. Messaging: `Callout`, `Notification`, `Tooltip`, `Badge`, `CornerBadge`. Display: `Table`, `Image`, `ImageLightbox`, `ProgressBar`, `SectionDivider`, `SideNavigation`, `CodeSnippet`.
12
+ Before choosing, run `npx live-tokens components`. The list holds every component the project has, shipped and custom, with each one's variants and usage comment. The family tests below name the shipped set only. Weigh a custom component by the same tests.
15
13
 
16
- That line is the shipped set. A project can register components of its own,
17
- and those never appear in this file: run `npx live-tokens components` before
18
- choosing. It lists every component the project has, shipped and custom, with
19
- the variants each takes and the purpose its header comment states, so a custom
20
- component is weighed against the shipped set on the same footing.
21
- `npx live-tokens components <id>` prints one component's props, the values each
22
- union accepts, and its tokens with defaults; `--json` returns the same as data.
14
+ ## Action family
23
15
 
24
- ## Action family: Button vs IconButton
16
+ - The action needs a word to be unambiguous: `Button`.
17
+ - The glyph alone is plain (close, edit, delete) and space is short: `IconButton`.
18
+ - The pair that confirms or cancels an inline edit: `InlineEditActions`.
25
19
 
26
- Both trigger an action and share the same six variants (primary, secondary, outline, success, danger, warning), three states (default, hover, disabled) and two sizes (default, small). They differ only in content.
20
+ ## Single-selection family
27
21
 
28
- - `Button` carries a text label, optionally with a leading or trailing icon. Use it whenever the action needs a word to be unambiguous.
29
- - `IconButton` is icon-only and square. Use it for compact, space-constrained actions whose meaning is obvious from the glyph alone (toolbar controls, close/edit/delete affordances, card overflow menus). It has no text slot, so an `ariaLabel` is required for accessibility.
30
- - **Don't reach for `IconButton` when the icon's meaning isn't self-evident.** A labelled `Button` (or a `Button` with an icon) avoids the guessing game.
31
- - `InlineEditActions` is the confirm-and-cancel pair that follows an inline edit (rename a row, edit a value in place). Use it rather than two loose `IconButton`s so every inline edit on the page resolves the same way.
22
+ Four components pick one option from a set. The test is the option count, whether the selection swaps the content below, and how much the choice asks of the reader.
32
23
 
33
- ## Single-selection family: SegmentedControl vs TabBar vs RadioButton vs MenuSelect
24
+ | Component | Test | Option count |
25
+ |---|---|---|
26
+ | `SegmentedControl` | An inline switch between views of the same data. It sits in a row of controls. | 2 to 4 |
27
+ | `TabBar` | The content area below swaps. | 2 to 7 |
28
+ | `RadioButton` | The reader reads every option as text inside a larger form. | any |
29
+ | `MenuSelect` | The options would overflow a row. | any |
34
30
 
35
- All four pick one option from a set. The right one depends on **option count**, **whether the selection changes what's rendered below**, and **how much visual weight** you want.
31
+ - When a label would wrap in a `SegmentedControl`, use `RadioButton` rows.
32
+ - The URL changes: `SideNavigation`. Sections inside one page: `TabBar`.
36
33
 
37
- | Component | Best for | Visual weight | Option count |
38
- |-------------------|-------------------------------------------------------------------------|------------------|--------------|
39
- | `SegmentedControl`| Inline switch between alternative *views of the same data* | Compact pill | 2–4 |
40
- | `TabBar` | Switching between *tab panels* (content area swaps below) | Page-section | 2–7 |
41
- | `RadioButton` | Form-style selection where the user reviews all options as text | Form-row | Any |
42
- | `MenuSelect` | A list of options, one checked; renders open, so a dropdown toggles it from a `Button` | Open list | Any |
34
+ ## Text entry
43
35
 
44
- - `TabBar` implies "this changes the page"; `SegmentedControl` implies "this is one knob among others."
45
- - Use `RadioButton` when labels deserve room to breathe and the user is committing to a larger form.
46
- - Use `MenuSelect` when options would overflow horizontally or there are too many to display at once.
47
- - **Don't pick `SegmentedControl` when option labels are long enough to wrap.** It loses its compactness; use `RadioButton` rows instead.
36
+ The test is whether the answer comes from a predefined list of options.
48
37
 
49
- ## Text entry: Input vs the selection family
38
+ - A predefined list (a status, a currency, a size, a country): the single-selection family, by its own test. Up to four options sit in a row; more go in a `MenuSelect`, which scrolls.
39
+ - No list (a name, a search string, an amount, a message, a street address): `Input`. Validation keeps a typed answer well-formed.
40
+ - A long list the reader would rather filter by typing (a city): no shipped component filters a list. Use `Input` with validation, or author a filtering select with **live-tokens-create-component**.
41
+ - A number where the position on a track carries the meaning (a volume, a price band, a percentage): `Slider`. A number the reader knows and would rather type: `Input` with `type="number"`.
50
42
 
51
- - `Input` takes an answer the page cannot enumerate: a name, an email, a search string, an amount. It ships the label, the hint line, and the error state as parts (`--input-label-*`, `--input-hint-*`, `--input-error-*`), so style those rather than stacking your own text under a bare field.
52
- - The boundary is whether you can list the answers. A short fixed set is the single-selection family above; a long fixed set is `MenuSelect`; anything you cannot write down is `Input`.
53
- - `Slider` takes a number inside a known range where the position carries the meaning: a volume, a price band, a percentage. Its `range` variant takes a low and a high bound on one track. A number the user knows exactly and would rather type is `Input` with `type="number"`.
54
- - **Don't use it for on/off.** That is `Toggle`, and a one-field form asking for yes or no is the usual way this goes wrong.
55
- - Its four variants are `default`, `focused`, `disabled`, and `error`. A validation message belongs in the `error` variant, not in a `Callout` next to the field.
43
+ ## On and off
56
44
 
57
- ## Container family: Card vs CollapsibleSection vs Dialog
45
+ Three components express a binary choice. The test is whether the two states have names of their own.
58
46
 
59
- | Component | Modality | Use for |
60
- |-----------------------|---------------------|-------------------------------------------------------------|
61
- | `Card` | Inline, always open | Default container for grouped content |
62
- | `CollapsibleSection` | Inline, toggleable | Progressive disclosure inside a longer page |
63
- | `Dialog` | Modal, blocks page | Confirmations, focused tasks the page can't continue around |
64
- | `Panel` | Inline, fixed stage | A demo or preview surface whose height must not reflow |
47
+ | Component | Test |
48
+ |---|---|
49
+ | `Toggle` | A setting that takes effect at once. The label names the setting. The switch position is the state. |
50
+ | `SegmentedControl` | Two named alternatives the reader compares (Light / Dark, List / Grid). Both labels show at once. |
51
+ | `RadioButton` pair | A yes or no the reader answers inside a larger form. |
65
52
 
66
- - Default to `Card`. It's the workhorse. For full-bleed media (cover art, a poster, a chart that reaches its own border) pass `flush` (with `prose={false}`) rather than zeroing its padding tokens from the page.
67
- - Reach for `CollapsibleSection` only when the content is *legitimately secondary* (advanced users open it; most skip). Don't use collapse as a styling choice when the content matters.
68
- - `Panel` is a stage, not a content container. It pins its own height so what it shows can resize without moving the page, which is what a component preview or a live example needs and what article content does not. Content goes in `Card`.
69
- - **Don't use `Dialog` for routine forms.** Reach for it only when the page cannot meaningfully continue until the user decides (destructive confirmations, payment, sign-in). Routine forms go inline in a `Card`.
53
+ When the two states share the feature's one name, use `Toggle`. "Email notifications" has no "off" label.
70
54
 
71
- ## Messaging family: Callout vs Notification vs Tooltip vs Badge
55
+ ## Container family
72
56
 
73
- | Component | Scope | Triggered by | Dismissable | Use for |
74
- |-----------------|----------------|-----------------|-------------|------------------------------------------------------|
75
- | `Callout` | Section-inline | Always present | No | "Heads up about this section" |
76
- | `Notification` | System-level | Event / save | Yes | "Your changes were saved" |
77
- | `Tooltip` | Element-inline | Hover / focus | Auto | Definition or hint anchored to an element |
78
- | `Badge` | Element-inline | Always present | No | Status pill ("Beta", "New", "v2") |
79
- | `CornerBadge` | Element-corner | Always present | No | Position-anchored marker (count, status dot) |
57
+ Four components hold a block of content. The test is what the block is to the reader: one item, a section of the page, secondary content that stays collapsed until opened, or a decision.
80
58
 
81
- - `Callout` is *content*. Part of the section, written into the markup, says something important about what surrounds it. Variants (`info`, `success`, `warning`, `danger`) set the tone.
82
- - `Notification` is *feedback*. Appears in response to an action, then dismisses. **Don't use `Notification` for static content;** persistent messages belong in a `Callout`.
83
- - `Tooltip` is for *what an element means*. **Don't use `Tooltip` as the primary location of important content;** it auto-dismisses and isn't accessible for must-read content.
84
- - `Badge` and `CornerBadge` differ only in positioning. `CornerBadge` lives at a `top-right` / `bottom-left` anchor on a parent (notification counts, "NEW" stickers).
59
+ | Component | Modality | Test |
60
+ |---|---|---|
61
+ | `Card` | Inline, always open | One item, or each item in a set: a product, a record, a plan. It has a title and can react to hover. |
62
+ | `Panel` | Inline, always open | One section of the page's content in a frame: a stage, a list, a form, a block of copy. `minHeight` holds its height while the content changes. |
63
+ | `CollapsibleSection` | Inline, collapsed until the reader opens it | Secondary content most readers skip. |
64
+ | `Dialog` | Modal, blocks the page | A decision the page cannot continue without: a destructive confirmation, payment, sign-in. |
85
65
 
86
- ## Display family: shown, not asked
66
+ A set of items is one `Card` per item. A routine form goes inline in a `Panel`.
87
67
 
88
- - `Image` frames a picture in the flow at one of four sizes, with an optional hover zoom. It is the default for any picture the page simply shows.
89
- - `ImageLightbox` adds click-to-open at full size and takes an array for a gallery. Use it when the detail is the point (screenshots, artwork, charts that need reading), and not for decoration: it puts a modal behind every picture it wraps.
90
- - `Table` themes your own rows and cells without owning the data. Records go here; a set of *things the user acts on* is a stack of `Card`s instead.
91
- - `ProgressBar` reports progress against a labelled track. It is a read-out, never a control.
92
- - `CodeSnippet` is for a single-line command or value the reader is meant to copy back into a terminal (install commands, generated keys, ids), with click-to-copy and a brief "Copied" popover. Use it whenever the page asks the reader to *run* something rather than just *read* it.
93
- - `SectionDivider` separates sections of one page. `SideNavigation` moves between pages, driven by the current path. **Don't use `SideNavigation` to switch panels inside one page;** that is `TabBar`, and the difference is whether the URL changes.
68
+ ## Messaging family
94
69
 
95
- ## Toggle vs SegmentedControl vs RadioButton (for on/off)
70
+ Five components carry a message. The test is what the message is about, what brings it on, and whether the reader dismisses it.
96
71
 
97
- All three can express a binary choice. The right one depends on what the choice *is*.
72
+ | Component | Scope | Trigger | Dismissable | Test |
73
+ |---|---|---|---|---|
74
+ | `Callout` | A section | Always present | No | Something the reader must know about the content around it |
75
+ | `Notification` | The system | An action or event | Yes | Feedback about something that just happened |
76
+ | `Tooltip` | An element | Hover or focus | On leave | A definition or hint the reader can do without |
77
+ | `Badge` | An element | Always present | No | A standing label read at a glance ("Beta", "New", "v2") |
78
+ | `CornerBadge` | A parent's corner | Always present | No | A count or status marker on the thing it describes |
98
79
 
99
- | Component | Best for |
100
- |--------------------|-----------------------------------------------------------------------------------------------------------------------|
101
- | `Toggle` | A *setting* that's either on or off (notifications on/off, dark mode). The label names the setting; the switch shows the state. |
102
- | `SegmentedControl` | A *choice between two named alternatives* (Light / Dark, List / Grid). Both labels are visible at once. |
103
- | `RadioButton` pair | A *form-style choice* where the user reviews both labels before committing (Yes / No questions, opt-in selections). |
80
+ `Badge` and `CornerBadge` differ in position only.
104
81
 
105
- - If the off and on states share a name (the feature itself), it's `Toggle`. "Email notifications" has no "off" label because the switch position is the state.
106
- - If the two states have different names you want users to compare, it's `SegmentedControl`.
107
- - `Toggle` flips immediately; `RadioButton` pair is for forms where the choice is part of a larger submission.
82
+ ## Display family
108
83
 
109
- ---
84
+ Each pair holds a block the reader views and one the reader interacts with. The test is which of the two the page needs.
85
+
86
+ - A picture the page shows: `Image`. A picture whose detail the reader must open, or a gallery: `ImageLightbox`.
87
+ - Records the reader scans and compares: `Table`. A set of items the reader acts on: one `Card` per item.
88
+ - A read-out of progress: `ProgressBar`. A number the reader sets: `Slider`.
89
+ - Text the reader runs or pastes (an install command, a key, an id): `CodeSnippet`. Prose the reader only reads: a paragraph in its `Card` or `Panel`.
90
+ - A titled break between the sections of one page: `SectionDivider`. Movement between pages: `SideNavigation`.
91
+
92
+ ## Nothing fits
93
+
94
+ A native element with no chrome of its own needs no component: an `<input type="file">` behind a Button, a `<canvas>`, an `<img>` inside a stage. When nothing in the catalogue fits a piece with chrome (a `DatePicker`, a `Stepper`), author the component with **live-tokens-create-component**. Size, emphasis, and placement are **live-tokens-create-page**'s.
110
95
 
111
- If nothing in the catalogue fits (a `DatePicker`, a `Stepper`, a custom widget), author it via **live-tokens-create-component**. **Don't reach for a custom component before checking the catalogue;** a custom component is a maintenance commitment.
96
+ `npx live-tokens components <id>` prints one component's usage comment, its declared props, and the values each union accepts. `--json` returns the same as data.