@motion-proto/live-tokens 0.78.0 → 0.79.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 (166) hide show
  1. package/.claude/skills/live-tokens-check-compliance/SKILL.md +60 -31
  2. package/.claude/skills/live-tokens-create-component/SKILL.md +23 -28
  3. package/.claude/skills/live-tokens-create-component/references/contract-tests.md +61 -0
  4. package/.claude/skills/live-tokens-create-component/references/sketch-mode.md +2 -2
  5. package/.claude/skills/live-tokens-create-component/references/token-naming.md +6 -15
  6. package/.claude/skills/live-tokens-create-page/SKILL.md +6 -4
  7. package/.claude/skills/live-tokens-create-theme/references/design-directions.md +1 -1
  8. package/.claude/skills/live-tokens-pick-component/SKILL.md +3 -3
  9. package/.claude/skills/live-tokens-set-colors/references/color-anchors.md +1 -1
  10. package/.claude/skills/live-tokens-set-geometry/SKILL.md +1 -1
  11. package/.claude/skills/live-tokens-set-geometry/references/geometry-anchors.md +1 -1
  12. package/CHANGELOG.md +231 -0
  13. package/README.md +9 -15
  14. package/bin/check-component.mjs +152 -551
  15. package/bin/check-page.mjs +55 -541
  16. package/bin/cli.mjs +59 -13
  17. package/bin/contractRunner.mjs +37 -91
  18. package/bin/lib/catalogue.mjs +161 -34
  19. package/bin/lib/componentSource.mjs +152 -0
  20. package/bin/lib/cssValues.mjs +9 -0
  21. package/bin/lib/dataDir.mjs +126 -0
  22. package/bin/lib/findings.mjs +103 -12
  23. package/bin/lib/fixers.mjs +64 -0
  24. package/bin/lib/geometry.mjs +92 -0
  25. package/bin/lib/pageSource.mjs +230 -0
  26. package/bin/lib/report.mjs +57 -59
  27. package/bin/lib/tokenVocabulary.mjs +104 -34
  28. package/bin/rules/componentStructure.mjs +344 -0
  29. package/bin/rules/componentUse.mjs +313 -0
  30. package/bin/rules/importsAndRoutes.mjs +136 -0
  31. package/bin/rules/testRuns.mjs +122 -0
  32. package/bin/rules/tokens.mjs +363 -0
  33. package/bin/setup-claude.mjs +1 -2
  34. package/dist-plugin/{chunk-PDNL4NC5.js → chunk-D4WRIKEZ.js} +7 -2
  35. package/dist-plugin/{chunk-SWXRVZKT.js → chunk-REBHE3ZM.js} +414 -1
  36. package/dist-plugin/index.cjs +432 -15
  37. package/dist-plugin/index.js +8 -9
  38. package/dist-plugin/migrateData/index.cjs +422 -4
  39. package/dist-plugin/migrateData/index.js +2 -2
  40. package/dist-plugin/setColors/index.cjs +414 -1
  41. package/dist-plugin/setColors/index.d.cts +1 -1
  42. package/dist-plugin/setColors/index.d.ts +1 -1
  43. package/dist-plugin/setColors/index.js +1 -1
  44. package/dist-plugin/setGeometry/index.cjs +423 -13
  45. package/dist-plugin/setGeometry/index.d.cts +3 -3
  46. package/dist-plugin/setGeometry/index.d.ts +3 -3
  47. package/dist-plugin/setGeometry/index.js +10 -13
  48. package/dist-plugin/setType/index.d.cts +1 -1
  49. package/dist-plugin/setType/index.d.ts +1 -1
  50. package/dist-plugin/{themeTypes-BxRtuN5V.d.cts → themeTypes-B8_Idrp4.d.cts} +2 -2
  51. package/dist-plugin/{themeTypes-BxRtuN5V.d.ts → themeTypes-B8_Idrp4.d.ts} +2 -2
  52. package/package.json +2 -2
  53. package/src/editor/component-editor/CalloutEditor.svelte +2 -2
  54. package/src/editor/component-editor/CollapsibleSectionEditor.svelte +14 -15
  55. package/src/editor/component-editor/CornerBadgeEditor.svelte +14 -14
  56. package/src/editor/component-editor/DialogEditor.svelte +5 -5
  57. package/src/editor/component-editor/InlineEditActionsEditor.svelte +2 -2
  58. package/src/editor/component-editor/RadioButtonEditor.svelte +21 -21
  59. package/src/editor/component-editor/SectionDividerEditor.svelte +7 -7
  60. package/src/editor/component-editor/SegmentedControlEditor.svelte +5 -5
  61. package/src/editor/component-editor/SideNavigationEditor.svelte +25 -25
  62. package/src/editor/component-editor/TabBarEditor.svelte +6 -6
  63. package/src/editor/component-editor/TableEditor.svelte +6 -6
  64. package/src/editor/component-editor/ToggleEditor.svelte +2 -2
  65. package/src/editor/component-editor/index.ts +3 -0
  66. package/src/editor/component-editor/registry.ts +57 -1
  67. package/src/editor/component-editor/scaffolding/TokenLayout.svelte +14 -14
  68. package/src/editor/component-editor/scaffolding/VariantGroup.svelte +3 -0
  69. package/src/editor/component-editor/scaffolding/types.ts +15 -0
  70. package/src/editor/core/components/adjustAliases.ts +4 -4
  71. package/src/editor/core/components/aliasKinds.ts +20 -19
  72. package/src/editor/core/sketch/sketchLayer.ts +3 -3
  73. package/src/editor/core/themes/migrateComponentConfig.ts +14 -6
  74. package/src/editor/core/themes/migrations/2026-09-13-badge-brand.ts +42 -0
  75. package/src/editor/core/themes/migrations/2026-09-13-collapsiblesection-open.ts +33 -0
  76. package/src/editor/core/themes/migrations/2026-09-13-cornerbadge-prefix.ts +70 -0
  77. package/src/editor/core/themes/migrations/2026-09-13-hairline.ts +92 -0
  78. package/src/editor/core/themes/migrations/2026-09-13-indicator.ts +54 -0
  79. package/src/editor/core/themes/migrations/2026-09-13-sectiondivider-surface.ts +36 -0
  80. package/src/editor/core/themes/migrations/2026-09-13-selected-state.ts +124 -0
  81. package/src/editor/core/themes/migrations/2026-09-13-toggle-label.ts +31 -0
  82. package/src/editor/core/themes/migrations/index.ts +16 -0
  83. package/src/editor/core/themes/themeService.ts +3 -3
  84. package/src/editor/core/themes/themeTypes.ts +13 -15
  85. package/src/editor/docs/Docs.svelte +1 -1
  86. package/src/editor/docs/content/light-and-dark.md +3 -3
  87. package/src/editor/docs/content.generated.ts +1 -1
  88. package/src/editor/index.ts +1 -0
  89. package/src/editor/overlay/LiveEditorOverlay.svelte +15 -0
  90. package/src/editor/skill-atlas/SkillAtlas.svelte +4 -4
  91. package/src/editor/skill-atlas/TreeNodeCard.svelte +4 -4
  92. package/src/editor/skill-atlas/skillSources.generated.ts +11 -14
  93. package/src/editor/skill-atlas/skillTrees.ts +1 -3
  94. package/src/editor/skill-atlas/trees/check-compliance.ts +258 -93
  95. package/src/editor/skill-atlas/trees/create-component.ts +73 -62
  96. package/src/editor/skill-atlas/trees/create-page.ts +38 -17
  97. package/src/editor/skill-atlas/trees/pick-component.ts +3 -3
  98. package/src/editor/skill-atlas/trees/set-geometry.ts +1 -1
  99. package/src/editor/ui/UIPaletteSelector.svelte +11 -15
  100. package/src/editor/ui/variantScales.ts +8 -8
  101. package/src/live-tokens/data/themes/autumn.json +188 -188
  102. package/src/live-tokens/data/themes/halloween.json +188 -188
  103. package/src/live-tokens/data/themes/midnight-study.json +245 -245
  104. package/src/live-tokens/data/themes/ocean.json +188 -188
  105. package/src/live-tokens/data/themes/royal-velvet.json +188 -188
  106. package/src/live-tokens/data/themes/sketchy.json +188 -188
  107. package/src/live-tokens/data/themes/spring-meadow.json +188 -188
  108. package/src/live-tokens/data/themes/sunset.json +188 -188
  109. package/src/system/components/Badge.svelte +27 -23
  110. package/src/system/components/Button.svelte +13 -7
  111. package/src/system/components/Callout.svelte +16 -11
  112. package/src/system/components/Card.svelte +22 -15
  113. package/src/system/components/CodeSnippet.svelte +10 -6
  114. package/src/system/components/CollapsibleSection.svelte +68 -63
  115. package/src/system/components/CornerBadge.svelte +78 -72
  116. package/src/system/components/Dialog.svelte +21 -18
  117. package/src/system/components/IconButton.svelte +13 -9
  118. package/src/system/components/Image.svelte +14 -8
  119. package/src/system/components/ImageLightbox.svelte +10 -6
  120. package/src/system/components/InlineEditActions.svelte +17 -14
  121. package/src/system/components/Input.svelte +13 -7
  122. package/src/system/components/MenuSelect.svelte +13 -7
  123. package/src/system/components/Notification.svelte +17 -11
  124. package/src/system/components/Panel.svelte +13 -6
  125. package/src/system/components/ProgressBar.svelte +10 -5
  126. package/src/system/components/RadioButton.svelte +33 -30
  127. package/src/system/components/SectionDivider.svelte +28 -21
  128. package/src/system/components/SegmentedControl.svelte +27 -23
  129. package/src/system/components/SideNavigation.svelte +175 -171
  130. package/src/system/components/Slider.svelte +11 -7
  131. package/src/system/components/TabBar.svelte +53 -49
  132. package/src/system/components/Table.svelte +20 -15
  133. package/src/system/components/Toggle.svelte +14 -10
  134. package/src/system/components/Tooltip.svelte +10 -6
  135. package/src/system/styles/CONVENTIONS.md +3 -4
  136. package/src/testing-js/chunk-3UKGXCDL.js +48 -0
  137. package/src/testing-js/chunk-3UKGXCDL.js.map +1 -0
  138. package/src/testing-js/{chunk-FAFOAWYL.js → chunk-Q3YIAAG3.js} +17 -3
  139. package/src/testing-js/chunk-Q3YIAAG3.js.map +1 -0
  140. package/src/testing-js/{chunk-GNIUPIU2.js → chunk-U7OJE5DU.js} +18 -18
  141. package/src/testing-js/chunk-U7OJE5DU.js.map +1 -0
  142. package/src/testing-js/{chunk-4JQX6WWL.js → chunk-ZMZQZ33J.js} +474 -166
  143. package/src/testing-js/chunk-ZMZQZ33J.js.map +1 -0
  144. package/src/testing-js/component-behavior.contract.js +155 -0
  145. package/src/testing-js/component-behavior.contract.js.map +1 -0
  146. package/src/testing-js/component-editor.contract.js +6 -4
  147. package/src/testing-js/component-editor.contract.js.map +1 -1
  148. package/src/testing-js/component-render.contract.js +14 -10
  149. package/src/testing-js/component-render.contract.js.map +1 -1
  150. package/src/testing-js/index.d.ts +44 -4
  151. package/src/testing-js/index.js +13 -7
  152. package/src/testing-js/index.js.map +1 -1
  153. package/src/testing-js/page-compliance.contract.js +48 -10
  154. package/src/testing-js/page-compliance.contract.js.map +1 -1
  155. package/src/testing-js/registry.contract.js +5 -3
  156. package/src/testing-js/registry.contract.js.map +1 -1
  157. package/src/testing-js/{vitest-C-wNWcoA.d.ts → vitest-BMLIbDs2.d.ts} +8 -2
  158. package/src/testing-js/vitest.d.ts +1 -1
  159. package/src/testing-js/vitest.js +2 -1
  160. package/template/package.json +1 -1
  161. package/.claude/skills/live-tokens-create-component/SKILL copy.md +0 -196
  162. package/.claude/skills/live-tokens-fix-findings/SKILL.md +0 -105
  163. package/src/editor/skill-atlas/trees/fix-findings.ts +0 -504
  164. package/src/testing-js/chunk-4JQX6WWL.js.map +0 -1
  165. package/src/testing-js/chunk-FAFOAWYL.js.map +0 -1
  166. package/src/testing-js/chunk-GNIUPIU2.js.map +0 -1
@@ -1,47 +1,76 @@
1
1
  ---
2
2
  name: live-tokens-check-compliance
3
- description: Report an existing project's adherence to @motion-proto/live-tokens from one run of npx live-tokens report. Checks for correct use of components, properties, and tokens. The report names the tokens each component reads, the component each page renders, the findings of both checkers, and the recommended fixes. Called as the verification step by live-tokens-create-page and live-tokens-create-component. Use when the user asks to check, audit, or review the project. Edits no file. Hands the fix list to live-tokens-fix-findings.
3
+ description: Check an existing @motion-proto/live-tokens project against the design system and fix it until check-page and check-component both exit 0. Checks for correct use of components, properties, and tokens. Reads the whole project from one run of npx live-tokens report, runs the token migrations, then runs both checkers, which apply every auto repair and return each remaining finding with its own guidance, repair level, and details. Use when the user asks to check, audit, or review the project. Use when the user asks to fix the project or to make check:design pass. Edits the files the checkers name. Updates tokens.css only through the migration command.
4
4
  ---
5
5
 
6
- # Checking a project's adherence to live-tokens
6
+ # Checking and fixing a project's adherence to live-tokens
7
7
 
8
- Run `npx live-tokens report`. The CLI prints a report with the sections in the Report sections table. Say what each finding means and what the fix would cost. When live-tokens-create-page or live-tokens-create-component calls this skill, lead with the findings on the file it built. Edit no file. When the user wants the fixes applied, hand the fix list to **live-tokens-fix-findings**.
8
+ Check the project, then 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 the project's own components. Every token names a semantic property, and its default is the design token that property reads. Every finding carries its own `guidance`, and the repair follows it.
9
9
 
10
- `report` never runs the component contract suites. The `check-component` test run does, and it is what live-tokens-create-component calls to validate a component's runtime behavior.
11
-
12
- `report` stays static for pages too. The `check-page` test run is what live-tokens-create-page calls for a rendered page, in a browser against the project's own route, and it reports `page-component-paint`, `page-text-style`, `page-contrast`, `page-grid`, and `page-overflow` findings the same way `report`'s static findings read: by rule, with a fix.
10
+ The report and both checkers are static. They read the project's source, never open a browser, and never mount a runtime. `npx live-tokens check-page <file> --tests` proves a page's rendered paint, and `npx live-tokens check-component <id> --tests` proves a component's declared behavior. **live-tokens-create-page** and **live-tokens-create-component** run those, one file or one id at a time, and their findings carry guidance the same way.
13
11
 
14
12
  ## Workflow
15
13
 
16
- When `report` is an unknown command, route the dependency upgrade to **live-tokens-fix-findings**. Resume the audit after the upgrade.
17
-
18
- 1. Run `npx live-tokens report --json`.
19
- 2. Read each section of the report with the Report sections table.
20
- 3. When a finding needs component or token scale details, run the matching inspection command below. Otherwise continue with classification.
21
- 4. Classify each finding as Mechanical, Judgement, or Deliberate. For Deliberate findings, name the narrower config entry.
22
- 5. Reply with the findings of each section in the table's order, each with its count.
23
- 6. List the recommended fixes, each marked with its finding class, in the order **live-tokens-fix-findings** takes them.
24
- 7. End with the hand-off: run **live-tokens-fix-findings** on the list, or on the subset the user chooses.
14
+ 1. Run `npx live-tokens report --json`. Read it in its own key order: `project`, `migrations`, `components`, `findings.pages`, `findings.components`, `usage`, per Report sections below.
15
+ 2. Run `npx live-tokens migrate --check` to see the plan, then `npx live-tokens migrate` to apply it. The command brings `tokens.css` up to the installed package and heals the data tree. With `--write` it also rewrites the route references it lists. `--tokens <path>` names a tokens.css in an unusual place.
16
+ 3. Run both checkers with `--json`. Each first applies every finding whose `repair` is `auto`, checks again, and returns the fixes it applied in `fix.applied` beside the findings that remain. A fix in `fix.skipped` found its text moved, and the next run applies it. `--no-fix` reports without editing, for a build or CI.
17
+ ```sh
18
+ npx live-tokens check-page --json
19
+ npx live-tokens check-component --json
20
+ ```
21
+ 4. Read what remains. Each finding carries the fields under Finding fields, with a `repair` of `choice` or `authored`.
22
+ 5. Group the findings by rule. Take the largest error group first, then the remaining errors. Take warnings only when the repair scope includes warnings.
23
+ 6. Make every repair in the group from its `guidance`, within Scope below.
24
+ 7. Run both checkers again. When repairable findings remain in scope, return to step 5. When no token fits a remaining finding, leave it and continue to the reply with its reason.
25
+ 8. 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.
26
+ 9. When the repair scope includes warnings, return to step 5 with `--strict`. When strict checks pass or the user defers warnings, set up the build script.
27
+ 10. Add `check:design` to the build, per Build script below.
28
+ 11. Reply with:
29
+ - the report's picture: pending migrations, component facts, and usage
30
+ - the fixes the checkers applied, each with its count and any visible shift
31
+ - the remaining changes by rule, each with its count and any visible shift
32
+ - the findings left, each with its reason and any config entry the user chose
33
+ - both checker commands with their exit codes
25
34
 
26
- For one component, run `npx live-tokens components <id>`. For one token scale, run `npx live-tokens tokens --scale <name>`. Both take `--json`.
35
+ `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.
27
36
 
28
37
  ## Report sections
29
38
 
30
- | Section | Contents | Fix |
31
- | --- | --- | --- |
32
- | Pending token migrations (`migrations`) | Whether `tokens.css` is behind the installed package. `status` is `pending`, `none pending`, `no tokens.css`, or `unavailable`. A stale file shows downstream as unknown tokens. | Fix this first. Run `npx live-tokens migrate --check` to see the plan, then `npx live-tokens migrate` to apply it. `--write` also rewrites the route references the plan lists. `--tokens <path>` names a tokens.css in an unusual place. |
33
- | Checker findings by rule (`findings.pages`, `findings.components`) | Both checkers' findings by rule under the project's severities, and one strict total with every warning as an error. Errors fail the build today. The strict total is what a fully tokenized project would fail. | Classify each finding under Finding classes. |
34
- | Tokens a component never reads (`components[].unread`) | Tokens a component declares and never reads. Each is an editor row that edits nothing. | Wire each token into the CSS, or remove it. No checker rule covers this, so confirm with a second `report` run. |
35
- | Component registration (`components[].registered`) | Whether the component has a `bootLiveTokens` or `registerComponent` entry. Without one it renders with no editor. | Register it. |
36
- | Component usage comment (`components[].described`) | Whether the runtime file has the header comment the picker reads. Without one, `live-tokens components` cannot say what the component is for. | Add the comment. No checker rule covers this, so confirm with a second `report` run. |
37
- | Components each page renders (`usage.byPage`) | Which component each page imports, and how many times the page renders it. | When a page renders none, say whether it is chrome or markup that a shipped component covers. |
38
- | Shipped components no page renders (`usage.unusedShipped`) | Shipped components no page renders. | None. Information only. |
39
- | Project components unregistered or unused (`usage.customUnregistered`, `usage.customUnused`) | The project's own components that are unregistered or unused. | Register or delete each. `check-component` sees a component only under `src/system/components`, so confirm with a second `report` run. |
39
+ | Section | Contents |
40
+ | --- | --- |
41
+ | Pending token migrations (`migrations`) | Whether `tokens.css` is behind the installed package. `status` is `pending`, `none pending`, `no tokens.css`, or `unavailable`. A stale file shows downstream as unknown tokens, so step 2 runs the migrations before either checker. |
42
+ | Component facts (`components[]`) | Every component the project has, each with `id`, `origin`, `file`, `registered`, and `tokens` (the count of semantic properties it declares). A component's unread tokens, missing description, and missing registration are the `unread-token`, `missing-description`, and `missing-registration` findings. |
43
+ | Checker findings by rule (`findings.pages`, `findings.components`) | Both checkers' findings by rule under the project's severities, and one strict total with every warning as an error. Errors fail the build today. The strict total is what a fully tokenized project would fail. |
44
+ | Components each page renders (`usage.byPage`) | Which component each page imports, and how many times the page renders it. When a page renders none, say whether it is chrome or markup that a shipped component covers. |
45
+ | Shipped components no page renders (`usage.unusedShipped`) | Information only. |
46
+ | Project components unused (`usage.customUnused`) | The project's own components no page renders. |
47
+
48
+ ## Finding fields
49
+
50
+ Every finding from both checkers, under `report --json` and under each checker's `--json`:
51
+
52
+ | Field | Value |
53
+ | --- | --- |
54
+ | `rule`, `severity`, `file`, `line`, `message` | What the finding is and where. |
55
+ | `guidance` | How to make the repair: the token for the role or the scale step, the command that prints the candidates, or the section of a create skill that owns the fix. |
56
+ | `repair` | `auto`, `choice`, or `authored`. See Repair levels. |
57
+ | `exception` | The narrower config entry that records a decision to leave the finding as it is: `{ "checks": { "exclude": ["<file>"] } }` for a page or CSS file, otherwise `{ "checks": { "rules": { "<rule>": "warn" } } }`. Applying it steps the rule down one level, error to warn and warn to off. |
58
+ | `details` | Per-rule data the message already states in prose, such as the accepted values behind `unknown-prop-value` or the nearest design-token candidates behind `dimension-literal`. Absent when a rule has nothing to add. |
59
+
60
+ ## Repair levels
61
+
62
+ Every finding's `repair` says what moving it costs.
63
+
64
+ - **`auto`.** The value determines the fix, such as a spacing literal with one nearest design-token step. The checkers apply it and list it in `fix.applied`.
65
+ - **`choice`.** A role or an ambiguous value determines the fix, such as a color literal and the role it plays, or a spacing literal tied between two steps. `details` lists the candidates, and `guidance` says how to pick one.
66
+ - **`authored`.** New code is the fix: a runtime that has to start behaving, an editor schema that has to name a token, a route that has to move. `guidance` names what to write. No candidate list applies.
67
+
68
+ ## Scope
40
69
 
41
- ## Finding classes
70
+ - 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.
71
+ - When the nearest token differs from the literal, use the token and name the shift in the reply, such as `14px` to `--space-16`.
72
+ - Any finding, at any repair level, can stay as a deliberate exception when the user chooses to keep it. Record that decision in the config entry its `exception` field names, and prefer the narrower entry. 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.
42
73
 
43
- Every finding is one of three. Say which.
74
+ ## Build script
44
75
 
45
- - **Mechanical.** The value determines the token, such as a spacing literal and its nearest `--space-*` step. When the fix shifts a rendered value, name the shift.
46
- - **Judgement.** A role determines the token, such as a color literal and the role it plays. Say what the options are. Ask the user to choose.
47
- - **Deliberate.** The finding records a decision, such as a layout size the project owns. Name the config entry that would record the decision. Leave the decision to the user. To lower a rule's severity everywhere, the entry is `"checks": { "rules": { "<rule>": "warn" } }` in `live-tokens.config.json`. To drop one file that is not a themed surface, the entry is `"checks": { "exclude": ["src/art/hero.css"] }`. The path is project-relative, and a directory covers what is under it. Prefer the narrower entry.
76
+ When `package.json` has no `check:design` script, add `"check:design": "live-tokens check-page --no-fix && live-tokens check-component --no-fix"`. `--no-fix` keeps the build from editing files. When both checkers exit 0, prepend `npm run check:design &&` to the existing build command. Preserve its other build steps.
@@ -11,10 +11,10 @@ Create a component whose structure and behavior serve the user's purpose. Give e
11
11
 
12
12
  1. Read the project: `package.json`, `live-tokens.config.json`, `src/main.ts`, the catalogue, the token scales the component will use, a shipped runtime and editor pair, and the property suffixes.
13
13
  2. Design the properties: separate the component's parts, variants, and states, then write one row per editable role with its token and the CSS it controls, named the way the shipped components name the same role.
14
- 3. Write the runtime file: the usage comment and the `:global(:root)` block. A structural choice is an intrinsic. Every component joins the sketch layer, and a fixed overlay portals to `<body>`.
14
+ 3. Write the runtime file: the catalogue export and the `:global(:root)` block. A structural choice is an intrinsic. Every component joins the sketch layer, and a fixed overlay portals to `<body>`.
15
15
  4. Write the editor file: the schema, the preview props, and the markup. Variants that share a value are linked.
16
16
  5. Register the component in the module `src/main.ts` and `live-tokens.testing.ts` both name, and write its contract in the module `contractsModule` names.
17
- 6. Run **live-tokens-check-compliance**, then `npx live-tokens check-component <id> --tests --strict --json` until exit 0 with complete applicable coverage, then the Svelte check and the build.
17
+ 6. Run `npx live-tokens check-component <id> --tests --strict --json` until it exits 0 with complete applicable coverage, then the Svelte check and the build.
18
18
  7. Reply with the files, the id, the props, and each check's result. Then place the component on a page with **live-tokens-create-page**.
19
19
 
20
20
  ## Design model
@@ -34,12 +34,14 @@ A component is distinct in its anatomy, its proportions, its content hierarchy,
34
34
 
35
35
  Props carry content and behavior: a value, a label, a callback. Properties carry the editable appearance. When a variant is a choice the page makes, expose it as a prop.
36
36
 
37
+ Prop names follow the shipped components. `label` names a control, `title` heads content, `text` is body copy. `open` is the one prop for an open state. `value` holds a selection's id. A size prop's values are `default` and `small`. A callback prop is `on` followed by the event name, all lowercase, as in `onchange`, `onclose`, and `onsave`.
38
+
37
39
  ## Source inspection
38
40
 
39
41
  Before writing a file:
40
42
 
41
43
  1. Read the project's `package.json`, `live-tokens.config.json`, and `src/main.ts`.
42
- 2. Run `npx live-tokens components`. The list holds every component the project has, with its variants and usage comment. `npx live-tokens components <id>` prints one component's props.
44
+ 2. Run `npx live-tokens components`. The list holds every component the project has, with its variants and catalogue entry. `npx live-tokens components <id>` prints one component's props.
43
45
  3. Run `npx live-tokens tokens --scale <name>` for each token scale the component will use. Those names are the tokens a property can reference.
44
46
  4. Read a shipped runtime and editor pair: `Toggle` for interaction states, `Badge` for variants and linked values, `Card` for text and container parts.
45
47
  5. Read `references/token-naming.md` for the suffixes that select editor controls.
@@ -53,7 +55,7 @@ A component has three kinds of division. Keep them apart in the props, the names
53
55
  | Kind | Meaning | Example |
54
56
  |---|---|---|
55
57
  | Part | Regions present at once | Dialog's overlay, header, body, footer |
56
- | Variant | Alternative presentations the page chooses | Badge's primary, danger |
58
+ | Variant | Alternative presentations the page chooses | Badge's brand, danger |
57
59
  | State | A runtime condition | Toggle's on, hover, disabled |
58
60
 
59
61
  States have two axes. A component state is one of a set that excludes the others: default, selected (or on), disabled. An interaction state layers on a component state: default, hover, and later focus or active. `disabled` is terminal: no other state layers on it, in the names or in the editor.
@@ -95,20 +97,24 @@ A property name starts with the component id and ends with the property suffix.
95
97
 
96
98
  For a state that affects several parts, follow Toggle: `--toggle-on-hover-track-surface`. State segments precede the affected part.
97
99
 
98
- Name a role as the shipped component that paints the same thing names it. A fill is `-surface` in every shipped component. A knob is `-thumb`. A text role's color sits on the role's own name, `-title`, `-body`, `-label`, `-value`, and its typography hangs off that name: `--card-default-title-font-size`. A component with one text role uses `-text`: `--badge-primary-text`.
100
+ Name a role as the shipped component that paints the same thing names it. A fill is `-surface` in every shipped component. A knob is `-thumb`. A text role's color sits on the role's own name, `-title`, `-body`, `-label`, `-value`, and its typography hangs off that name: `--card-default-title-font-size`. A component with one text role uses `-text`: `--badge-brand-text`.
99
101
 
100
102
  ## Runtime component
101
103
 
102
104
  Create `src/system/components/StatCard.svelte`. `check-component` finds a runtime there only. A component in another directory is listed by `components` and `report` when that directory is named in `"componentDirs"` in `live-tokens.config.json`, and `check-component` does not check it. Use Svelte 5 props and snippets, semantic HTML, and the behavior the task requires.
103
105
 
104
- Open the file with an HTML comment in the shape every shipped component carries. `npx live-tokens components` prints the comment beside the id, and `components <id>` prints the props.
106
+ Open the file with a `<script module lang="ts">` block that exports a `catalogue` entry in the shape every shipped component carries. `npx live-tokens components` prints it beside the id, and `components <id>` prints it with the props. Each field is `key: <string literal>`, in single, double, or backtick quotes; no `${}` interpolation, no concatenation, no identifier reference. An optional `props` map adds one line per prop whose values carry a choice, such as `variant`; each key names a prop the file declares, and the text says what the values mean.
105
107
 
106
108
  ```svelte
107
- <!--
108
- StatCard.svelte. A figure with its label.
109
- Use for: one number the reader takes in at a glance.
110
- Not for: a set of records (Table); a titled block of content (Card).
111
- -->
109
+ <script module lang="ts">
110
+ import type { CatalogueEntry } from '@motion-proto/live-tokens';
111
+
112
+ export const catalogue = {
113
+ description: 'A figure with its label.',
114
+ useFor: 'one number the reader takes in at a glance.',
115
+ notFor: 'a set of records (Table); a titled block of content (Card).',
116
+ } satisfies CatalogueEntry;
117
+ </script>
112
118
  ```
113
119
 
114
120
  Declare every editable property in a literal `:global(:root)` block, each assigned a token. The plugin parses the Svelte source to seed `component-configs/<id>/default.json`, so the block holds plain declarations with no SCSS loop or interpolation.
@@ -192,6 +198,7 @@ Register the component in `src/registerComponents.ts`, a registration-only modul
192
198
  ```ts
193
199
  // src/registerComponents.ts
194
200
  import { registerComponent } from '@motion-proto/live-tokens';
201
+ import { catalogue } from './system/components/StatCard.svelte';
195
202
  import StatCardEditor, { allTokens as statCardTokens } from './system/components/StatCardEditor.svelte';
196
203
 
197
204
  registerComponent({
@@ -201,6 +208,7 @@ registerComponent({
201
208
  sourceFile: 'src/system/components/StatCard.svelte',
202
209
  editorComponent: StatCardEditor,
203
210
  schema: statCardTokens,
211
+ catalogue,
204
212
  });
205
213
  ```
206
214
 
@@ -218,23 +226,10 @@ A fixed overlay portals to `<body>`: read `references/fixed-overlays.md`. A cont
218
226
 
219
227
  ## Verification
220
228
 
221
- 1. Run **live-tokens-check-compliance** and address its findings with **live-tokens-fix-findings**. Then run `npx live-tokens check-component <id> --tests --strict --json`. Inside the live-tokens repository, run `node bin/cli.mjs check-component <id> --tests --strict --json`. Each finding carries a rule id and a line; `--off=<rule>` silences a rule for one run. `--tests` runs the registry contract and, for a component with a contract in the module `contractsModule` names, the component contract suites; its JSON reports coverage by rule. A `tests-not-installed` finding names the missing package; install `@playwright/test`, `vitest`, and `happy-dom` as devDependencies, then `npx playwright install chromium`. Fix every finding and rerun until exit 0 with complete applicable coverage and no disabled checks.
222
- 2. Run the project's Svelte check and its build.
223
- 3. Reply with the files, the component id, the props, and the results of steps 1 and 2, naming any check the environment prevented.
224
-
225
- Every finding carries a `fix` slug naming the section that fixes it.
226
-
227
- | `fix` | Section |
228
- |---|---|
229
- | `property-name` | Property design, the name |
230
- | `property-token` | Property design, the assigned token |
231
- | `runtime` | Runtime component |
232
- | `runtime-defaults` | Runtime component, the `:global(:root)` defaults |
233
- | `editor` | Component editor |
234
- | `registration` | Registration |
235
- | `sketch` | Sketch mode and overlays |
236
- | `tooling` | The message names the missing tool or the broken path; fix it and rerun |
237
- | `coverage` | Add the missing contract, or complete the run the message names |
229
+ 1. Run `npx live-tokens check-component <id> --tests --strict --json`. Inside the live-tokens repository, run `node bin/cli.mjs check-component <id> --tests --strict --json`. It applies every `auto` repair, runs the registry contract and, for a component with a contract in the module `contractsModule` names, the component contract suites, and returns the fixes it applied, the findings that remain, and coverage by rule. `--off=<rule>` silences a rule for one run, and `--no-fix` reports without editing.
230
+ 2. Each remaining finding carries a rule id, a line, and its `guidance`. Make each repair from its guidance, and run the command again until it exits 0 with complete applicable coverage and no disabled checks.
231
+ 3. Run the project's Svelte check and its build.
232
+ 4. Reply with the files, the component id, the props, and the result of each check, naming any check the environment prevented.
238
233
 
239
234
  `--tests` covers every line a reviewer once checked by eye: the component's listing, its controls and preview, persistence and reset, theme projection, linked properties, and Sketch mode.
240
235
 
@@ -152,10 +152,71 @@ Each obligation and what it needs from the project:
152
152
  to under it.
153
153
  - `interaction`: the interactive part's role and its cases. `applicable:
154
154
  false` for a component with no interactive role.
155
+ - `behavior`: what a callback prop does. See Behavior below.
155
156
  - `sketch`: a sketch style id and the fill and stroke each reserved-class part
156
157
  resolves to under it. `applicable: false` only for a component
157
158
  `references/sketch-mode.md` exempts.
158
159
 
160
+ ## Behavior
161
+
162
+ `behavior` runs under Vitest with `mount` from Svelte and happy-dom, not in
163
+ the editor preview, because a controlled component's callback prop has
164
+ nothing driving it there: the preview edits the token, not the prop. One
165
+ case names the props the runtime mounts with, the action a user takes, and
166
+ what that should do.
167
+
168
+ ```ts
169
+ behavior: {
170
+ cases: [
171
+ {
172
+ name: 'clicking an off toggle asks for on',
173
+ props: { checked: false },
174
+ action: { kind: 'click', part: 'root' },
175
+ expect: { kind: 'callback', prop: 'onchange', args: [true] },
176
+ },
177
+ {
178
+ name: 'clicking leaves the switch where the prop put it',
179
+ props: { checked: false },
180
+ action: { kind: 'click', part: 'root' },
181
+ expect: { kind: 'attribute', part: 'root', name: 'aria-checked', value: 'false' },
182
+ },
183
+ {
184
+ name: 'checked drives aria-checked',
185
+ props: { checked: true },
186
+ expect: { kind: 'attribute', part: 'root', name: 'aria-checked', value: 'true' },
187
+ },
188
+ {
189
+ name: 'a disabled toggle stays silent',
190
+ props: { checked: false, disabled: true },
191
+ action: { kind: 'click', part: 'root' },
192
+ expect: { kind: 'no-callback', prop: 'onchange' },
193
+ },
194
+ ],
195
+ },
196
+ ```
197
+
198
+ Toggle is controlled: it never flips `checked` itself, so the click case
199
+ that asks for `on` and the mount case that reads `checked` are two separate
200
+ cases, not one. The disabled case pins that a disabled toggle calls nothing
201
+ back: the prop reaches the DOM as a real `disabled` attribute on the part,
202
+ and happy-dom withholds a dispatched click from a disabled `<button>`. A
203
+ component that reports through `input` rather than `click`, such as Slider,
204
+ gets no disabled case, because happy-dom delivers a dispatched `input` event
205
+ to a disabled control and the case would assert the environment rather than
206
+ the component.
207
+
208
+ A component with no callback prop declares the obligation inapplicable, in
209
+ one line:
210
+
211
+ ```ts
212
+ behavior: { applicable: false, reason: 'a table wrapper declares no callback prop; its rows arrive as a snippet' },
213
+ ```
214
+
215
+ The fault this suite catches is a callback that fires with the wrong
216
+ argument, fires when a case says it should stay silent, or never fires at
217
+ all. `check-component <id> --tests` reports it as `contract-behavior`,
218
+ naming the case.
219
+
159
220
  ## Running vitest yourself
160
221
 
161
222
  `check-component --tests` covers the shipped path. Run vitest directly only
@@ -138,8 +138,8 @@ Make the rule an element, give it `sketch-rule`, and name its ink as the fill.
138
138
  ```css
139
139
  .mywidget-rule {
140
140
  height: var(--border-width-2);
141
- background: var(--mywidget-divider);
142
- --sketch-fill: var(--mywidget-divider);
141
+ background: var(--mywidget-hairline-color);
142
+ --sketch-fill: var(--mywidget-hairline-color);
143
143
  }
144
144
  ```
145
145
 
@@ -17,15 +17,12 @@ to that list, so the two cannot drift apart.
17
17
  | `-icon` | Icon color |
18
18
  | `-label` | Label text color |
19
19
  | `-fill` | Inner fill (distinct from outer surface) |
20
- | `-divider` | Divider / separator color |
21
- | `-color` | Generic color, when none of the above name the role |
20
+ | `-color` | A hairline rule's colour, or a color no role word above names |
22
21
  | `-shadow` | Box-shadow |
23
22
  | `-opacity` | Opacity (0–1) |
24
23
  | `-blur` | Backdrop or filter blur radius |
25
24
  | `-tint` | A wash over the surface, aliasing a `--tint-*` stop |
26
- | `-background` | Fill, where the component's own vocabulary says background |
27
- | `-accent` | An accent bar or indicator's colour |
28
- | `-indicator` | A selection indicator's colour |
25
+ | `-indicator` | The colour of the bar or stripe that marks an item |
29
26
  | `-thumb` | A scrollbar or slider thumb's colour |
30
27
  | `-title` | Title text colour |
31
28
  | `-body` | Body text colour |
@@ -42,21 +39,15 @@ to that list, so the two cannot drift apart.
42
39
  |-----------------|---------------------------------------------------------------|
43
40
  | `-radius` | Corner radius |
44
41
  | `-border-width` | Stroke thickness (used even when CSS uses `outline:`) |
45
- | `-thickness` | Alternative to `-width` when fallback siblings would collide |
46
- | `-accent-width` | An accent bar's thickness |
47
- | `-indicator-width` | An indicator's thickness, moved with `-accent-width` |
48
- | `-hairline-thickness` | A hairline rule's thickness |
42
+ | `-indicator-width` | An indicator's thickness |
43
+ | `-hairline-width` | A hairline rule's thickness |
49
44
  | `-dot-size` | A dot indicator's diameter |
50
- | `-divider-width` | A divider's thickness |
51
- | `-divider-thickness` | Alternative to `-divider-width` |
52
- | `-divider-height` | A divider's length |
53
- | `-divider-inset` | Inset trimmed from a stretched divider |
45
+ | `-hairline-inset` | Inset trimmed from a stretched hairline |
54
46
  | `-track-height` | A track's height (progress bar, slider) |
55
47
  | `-icon-size` | An icon's rendered size |
56
48
  | `-thumb-size` | A thumb's rendered size |
57
49
  | `-height` | A measured height (a track, a panel) |
58
50
  | `-margin` | Outer spacing, moved on the same scale as `-padding` |
59
- | `-inset` | Inset trimmed from a stretched element |
60
51
  | `-duration` | Motion duration |
61
52
  | `-easing` | Motion easing curve |
62
53
  | `-scale` | A transform scale factor |
@@ -67,7 +58,7 @@ to that list, so the two cannot drift apart.
67
58
 
68
59
  `-width`, `-height` and `-size` are the fall-through: any dimension with no
69
60
  more specific name behind it. They read the `--space-*` scale through the same
70
- picker `-gap` uses, and they match last, so `-border-width`, `-divider-height`,
61
+ picker `-gap` uses, and they match last, so `-border-width`, `-hairline-width`,
71
62
  `-icon-size` and the rest claim their token first. Reach for the specific name
72
63
  when one fits; a stroke is `-border-width` even where the CSS says `outline:`.
73
64
 
@@ -17,8 +17,8 @@ Assemble the page from the shipped components at their defaults and the theme's
17
17
  6. Write the page CSS in design tokens.
18
18
  7. Set the hierarchy: one text style per element, the shipped size on every control, one primary action, and one space step per position.
19
19
  8. Add the route, with a lazy import and the source path.
20
- 9. Run **live-tokens-check-compliance** and `npx live-tokens check-page <file> --tests --strict`, then check the rendered page.
21
- 10. Reply with the sections and the layout each took, the components placed, the route, and the compliance result.
20
+ 9. Run `npx live-tokens check-page <file> --tests --strict --json` until it exits 0, then check the rendered page.
21
+ 10. Reply with the sections and the layout each took, the components placed, the route, and the check-page result.
22
22
 
23
23
  ## Layout
24
24
 
@@ -85,7 +85,7 @@ Show related items side by side when the width permits. A line of copy runs 45 t
85
85
  ## Components
86
86
 
87
87
  - Use a shipped component when one fits. Import it from `@motion-proto/live-tokens/components/<Name>.svelte`.
88
- - `npx live-tokens components <id>` prints the declared props, the values each union accepts, and the usage comment. `--json` prints the same as data. The list includes the project's own components.
88
+ - `npx live-tokens components <id>` prints the declared props, the values each union accepts, and the catalogue entry. `--json` prints the same as data. The list includes the project's own components.
89
89
  - Pass only the props a component declares.
90
90
  - A shipped component fills its parent. To size one, size the element the page wraps it in.
91
91
  - 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.
@@ -165,7 +165,9 @@ const pages = {
165
165
 
166
166
  ## Verify
167
167
 
168
- Run **live-tokens-check-compliance**, then `npx live-tokens check-page <file> --tests --strict`. The Playwright suite runs against the page's own route and proves what only a rendered page can: the cascade leaves every component painting from its semantic properties, every run of text sits in one shipped text style, every text and surface pair meets AA, sections sit on the page grid, and nothing overflows. Each finding carries a rule id and a line; `--off=<rule>` silences a rule for one run. The two reports carry every finding by rule, and **live-tokens-fix-findings** takes the fix list. Repeat until the page is clean.
168
+ Run `npx live-tokens check-page <file> --tests --strict --json`. It applies every `auto` repair, runs the Playwright suite against the page's own route, and returns the fixes it applied and the findings that remain. The suite proves what only a rendered page can: the cascade leaves every component painting from its semantic properties, every run of text sits in one shipped text style, every text and surface pair meets AA, sections sit on the page grid, and nothing overflows. `--off=<rule>` silences a rule for one run, and `--no-fix` reports without editing.
169
+
170
+ Each remaining finding carries a rule id, a line, and its `guidance`. Make each remaining repair from its guidance, and run the command again until it exits 0.
169
171
 
170
172
  The checkers cannot see a layout. Open the page at the width it is built for and check each line below.
171
173
 
@@ -88,7 +88,7 @@ rather than only on the buttons.
88
88
  | Christmas | red and green with gold, one of the two owning the ground |
89
89
  | Halloween | pumpkin, violet, and poison green, dark either way |
90
90
  | St. Patrick's | green with gold over a pale ground |
91
- | Ocean | blues held to one narrow band |
91
+ | Ocean | blues held to one narrow range |
92
92
  | Sunset | a hue sweep through red, falling in lightness |
93
93
  | Autumn | parchment under rust, gold, and moss |
94
94
  | Spring | pastels, greens and pinks over a mint ground |
@@ -9,7 +9,7 @@ When more than one shipped component could fit, find the family below that names
9
9
 
10
10
  ## Catalogue
11
11
 
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.
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 catalogue entry. The family tests below name the shipped set only. Weigh a custom component by the same tests.
13
13
 
14
14
  ## Action family
15
15
 
@@ -38,7 +38,7 @@ The test is whether the answer comes from a predefined list of options.
38
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
39
  - No list (a name, a search string, an amount, a message, a street address): `Input`. Validation keeps a typed answer well-formed.
40
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"`.
41
+ - A number where the position on a track carries the meaning (a volume, a price range, a percentage): `Slider`. A number the reader knows and would rather type: `Input` with `type="number"`.
42
42
 
43
43
  ## On and off
44
44
 
@@ -93,4 +93,4 @@ Each pair holds a block the reader views and one the reader interacts with. The
93
93
 
94
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.
95
95
 
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.
96
+ `npx live-tokens components <id>` prints one component's catalogue entry, its declared props, and the values each union accepts. `--json` returns the same as data.
@@ -1,7 +1,7 @@
1
1
  # Color anchors: feelings, idioms, and occasions
2
2
 
3
3
  Read this when the color intent names one of these. Entries are starting
4
- points: apply the chroma budget, the per-role bands, and the canvas commitment
4
+ points: apply the chroma budget, the per-role ranges, and the canvas commitment
5
5
  rules from SKILL.md on top of them.
6
6
 
7
7
  An idiom sets constraints and overrides the generic defaults in SKILL.md. The
@@ -37,7 +37,7 @@ Targeted, absolute:
37
37
  ```
38
38
 
39
39
  - `target` (optional): a component id, one of the folder names under `src/live-tokens/data/component-configs/`. "Windows" or "modals" is `dialog`, "cards" is `card`, "tabs" is `tabbar`. "The UI", "everything", or no noun means global, so omit `target`.
40
- - `kind`: `radius | padding | gap | border-width | divider-width | accent-width`. `border-width` moves `-border-width` aliases. `divider-width` moves dividers, hairline rules, and `-thickness` aliases. `accent-width` moves accent bars and indicators.
40
+ - `kind`: `radius | padding | gap | border-width | hairline-width | indicator-width`. `border-width` moves `-border-width` aliases. `hairline-width` moves `-hairline-width` aliases. `indicator-width` moves the bar or stripe an indicator draws.
41
41
  - `set` or `shift`, one of the two. `set` takes a token on that kind's scale. `shift` is a whole number of steps and stops at the ends of the scale.
42
42
  - `full` (radius shifts only): admits `--radius-full` as the top of the scale. A pill request is `set: "--radius-full"` with no `full` flag.
43
43
 
@@ -7,7 +7,7 @@ came from, and a style's geometry is often targeted rather than global.
7
7
  Entries are written in the ops vocabulary. "radius +2" is a radius shift of 2.
8
8
  "borders +1" is a border-width shift of 1. "padding +1" is a padding and gap
9
9
  shift of 1. "hairline borders" is border-width `set: "--border-width-1"`, and
10
- "no borders" is `set: "--border-width-0"`. "hairline rules" is divider-width
10
+ "no borders" is `set: "--border-width-0"`. "hairline rules" is hairline-width
11
11
  `set: "--border-width-1"`. A named component means a targeted op. Controls squeeze before containers,
12
12
  so a compaction of more than one step still spends its extra steps on
13
13
  containers by name.