@motion-proto/live-tokens 0.72.0 → 0.72.1

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.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: live-tokens-adjust-geometry
3
- description: Adjust corner radius, padding, gap, and border width across live-tokens components by moving each token alias along the shipped scales. Use when the user asks for pill or capsule buttons; rounded, rounder, sharp, sharper, square, softer, or harder corners; thicker or thinner borders; or density space it out, tighter, denser, more compact, airier, more breathing room. Also invoked by live-tokens-generate-theme for the geometry half of a whole look. Changes shape and space aliases per component, never color, fonts, or tokens.css. Not for editing a single token (use the editor) or for color (see live-tokens-generate-theme).
3
+ description: Adjust corner radius, padding, gap, and border width across live-tokens components by moving each token alias along the shipped scales. Use when the user asks for pill or capsule buttons; rounded, rounder, sharp, sharper, square, softer, or harder corners; thicker or thinner borders; or density: space it out, tighter, denser, more compact, airier, more breathing room. Also invoked by live-tokens-generate-theme for the geometry half of a whole look. Changes shape and space aliases per component, never color, fonts, or tokens.css. Not for editing a single token (use the editor) or for color (see live-tokens-generate-theme).
4
4
  ---
5
5
 
6
6
  # Adjusting geometry
@@ -16,7 +16,7 @@ Text inside a `Card` or a `CollapsibleSection` is typed by that container, not b
16
16
 
17
17
  ## Layout
18
18
 
19
- Pages sit inside the column grid via `--columns-count`, `--columns-gutter`, `--columns-max-width`. Toggle `ColumnsOverlay` (Cmd+G in dev) to visualise it while placing content.
19
+ Pages sit inside the column grid via `--columns-count`, `--columns-gutter`, `--columns-max-width`. The columns button in the overlay's header (the vertical-lines icon) draws the grid over the page while you place content.
20
20
 
21
21
  To place children at specific page-column positions, span the parent grid (`grid-column: 1 / -1`), redeclare `repeat(var(--columns-count), 1fr)` with `--columns-gutter`, then refer to children by real page-column numbers. Never fabricate a local `repeat(N, 1fr)` with a hardcoded count: the widths drift from the page grid and the numbers stop matching `ColumnsOverlay`.
22
22
 
@@ -61,8 +61,8 @@ npx live-tokens check-page src/pages/YourPage.svelte
61
61
  # or: npx @motion-proto/live-tokens check-page (every page under src/)
62
62
  ```
63
63
 
64
- It fails on a component outside the catalogue, a prop a component does not declare, a variant or size outside the prop's union, a deep import, a `var()` that resolves to nothing, a colour literal in any notation, a route under `/live-tokens/*`, and `site.css` imported from `main.ts`. It warns on a px or rem literal in spacing, stroke, radius, or shadow, a hardcoded column count of four or more, an absolute type value, and a route entry with no `source`. Inline `style=` attributes and `style:` directives are read the same way as the `<style>` block; a `var()` fallback is not the page's value and is never a finding.
64
+ It fails on a component outside the catalogue, a prop or value the component does not declare, a deep import, a `var()` that resolves to nothing, a colour literal in any notation, a route under `/live-tokens/*`, and `site.css` imported from `main.ts`. It warns on a px or rem literal in the geometry the theme owns, a hardcoded page-column count, a raw type axis, and a route entry with no `source`. Inline `style=` attributes and `style:` directives are read the same way as the `<style>` block; a `var()` fallback is never a finding. The recipe for each rule is in **live-tokens-fix-findings**.
65
65
 
66
66
  Warnings do not fail the run. `--strict` makes them fail, which is the setting to use when the page is meant to be fully tokenized. `--json` prints findings with a stable `rule` id, so you can work through one rule at a time and re-run. `--off=<rule>` silences a rule for a run; `"checks": { "rules": { ... } }` in `live-tokens.config.json` sets it for the project. A project scaffolded by `create` runs the checker, with `check-component`, as `npm run check:design` before every `vite build`, so the page has to pass before it can ship.
67
67
 
68
- Then in dev: change a colour in `/live-tokens/editor` and confirm your page repaints (proves token usage). The overlay's "Page Source" button on the new route opens the page in VS Code (proves the route's `source`). `ColumnsOverlay` (Cmd+G) shows content sitting inside `--columns-max-width`.
68
+ Then in dev: change a colour in `/live-tokens/editor` and confirm your page repaints (proves token usage). The overlay's "Page Source" button on the new route opens the page in VS Code (proves the route's `source`). The columns overlay shows content sitting inside `--columns-max-width`.
@@ -5,23 +5,20 @@ description: Check an existing @motion-proto/live-tokens project against its des
5
5
 
6
6
  # Checking a project against its design system
7
7
 
8
- The answer to "check this project" is a report, and every fact in it comes
9
- from one command. This skill runs it, reads it, and says what the facts mean
10
- and what fixing them would involve. It edits nothing. When the user wants the
11
- changes made, that is **live-tokens-fix-findings**, and the report is what it
12
- starts from.
8
+ The answer to "check this project" is a report. Every fact in it comes from one command; the reading of those facts, and what fixing them would cost, is yours. This skill edits nothing. When the user wants the changes made, that is **live-tokens-fix-findings**, and this report is what it starts from.
13
9
 
14
- ## Run the report
10
+ ## Workflow
15
11
 
16
- ```sh
17
- npx live-tokens report --json
18
- ```
12
+ 1. Run `npx live-tokens report --json`. It always exits 0: it is a reading, not a gate. Unknown command means the installed package predates it; upgrade `@motion-proto/live-tokens` first.
13
+ 2. Read each section against the table below. For every rule with findings, say in a line what the rule holds and whether the fix is mechanical or a judgement.
14
+ 3. Where a finding looks deliberate, name the config entry that would record the decision, and leave the decision to the user.
15
+ 4. Report in the order under Summary, each line carrying its count, and end by handing the list to **live-tokens-fix-findings**. Do not start applying fixes here, even one-liners, because the user asked how things stand.
19
16
 
20
- It always exits 0: it is a reading, not a gate. Unknown command means the
21
- installed package predates it; upgrade `@motion-proto/live-tokens` first. The
22
- sections, in the order the report gives them:
17
+ `npx live-tokens components <id>` and `npx live-tokens tokens --family <name>` (both take `--json`) answer any question the report raises about one component or one scale.
23
18
 
24
- | Section | Fact | What it means when it is not clean |
19
+ ## The report's sections
20
+
21
+ | Section | Fact | When it is not clean |
25
22
  | --- | --- | --- |
26
23
  | `migrations` | Whether `tokens.css` is behind the installed package | A stale file shows up downstream as unknown tokens. This is the first fix, and it is one command: `npx live-tokens migrate --check`, then `--write` (`--tokens <path>` for a tokens.css in an unusual place). |
27
24
  | `components[].unread` | Tokens a component declares that nothing in its file reads | An editor row that edits nothing. Each is a token to wire into the CSS or to remove. |
@@ -32,47 +29,22 @@ sections, in the order the report gives them:
32
29
  | `usage.customUnregistered`, `usage.customUnused` | The project's own components that are unregistered or unused | Dead or half-wired work. |
33
30
  | `findings.pages`, `findings.components` | Both checkers' findings by rule, under the project's severities and again under `--strict` | The errors are what fails the build today; the strict count is what a fully tokenized project would fail. |
34
31
 
35
- `npx live-tokens components <id>` and `npx live-tokens tokens --family <name>`
36
- (both take `--json`) answer any question the report raises about one
37
- component or one scale.
38
-
39
- ## Read it
40
-
41
- Facts are the report's; the reading is yours. For each rule with findings, say
42
- in a line what the rule holds and which of two kinds the fix is:
32
+ ## Mechanical or judgement
43
33
 
44
- - **Mechanical**: a spacing literal to its nearest `--space-*` step, a stroke
45
- to `--border-width-*`, a hardcoded column count to `var(--columns-count)`,
46
- `site.css` moved out of `main.ts`, a route given its `source`. Name any
47
- visible shift, such as a `14px` margin becoming `16px`.
48
- - **Judgement**: a colour literal mapped by the role it plays rather than its
49
- hue, a raw type axis set from a text style, a prop the component does not
50
- declare mapped or dropped. Say what the choice is, not what you would pick.
34
+ - **Mechanical**: a spacing literal to its nearest `--space-*` step, a stroke to `--border-width-*`, a hardcoded column count to `var(--columns-count)`, `site.css` moved out of `main.ts`, a route given its `source`. Name any visible shift, such as a `14px` margin becoming `16px`.
35
+ - **Judgement**: a colour literal mapped by the role it plays rather than its hue, a raw type axis set from a text style, a prop the component does not declare mapped or dropped. Say what the choice is, not what you would pick.
51
36
 
52
- Where a finding looks deliberate, a translucent overlay on an app shell or a
53
- layout size the project owns, say so and name the config entry that would
54
- record the decision: `"checks": { "rules": { "<rule>": "warn" } }` in
55
- `live-tokens.config.json`. Where a whole file is not a themed surface at all,
56
- hand-tuned artwork or vendored CSS, the entry is
57
- `"checks": { "exclude": ["src/art/hero.css"] }` — a project-relative path, a
58
- directory covering what is under it, and naming the file on the command line
59
- still checks it. Prefer the narrower one: an exclusion drops one file, a
60
- severity change drops a rule everywhere. Recording either is the user's call,
61
- not yours.
37
+ ## Deliberate findings
62
38
 
63
- ## Report
39
+ A translucent overlay on an app shell, or a layout size the project owns, may be a decision rather than a miss. Say so and name the entry that would record it: `"checks": { "rules": { "<rule>": "warn" } }` in `live-tokens.config.json`. Where a whole file is not a themed surface at all, hand-tuned artwork or vendored CSS, the entry is `"checks": { "exclude": ["src/art/hero.css"] }`: a project-relative path, a directory covering what is under it, and naming the file on the command line still checks it. Prefer the narrower one: an exclusion drops one file, a severity change drops a rule everywhere. Recording either is the user's call, not yours.
64
40
 
65
- In this order, each line carrying its count:
41
+ ## Summary
66
42
 
67
43
  1. Migrations pending, and the one command that clears them.
68
44
  2. What fails the build now: errors by rule, with the files.
69
45
  3. What `--strict` would add: warnings by rule.
70
46
  4. Components: unread tokens, unregistered, undescribed.
71
47
  5. Usage: what each page renders, and what is used nowhere.
72
- 6. Recommended fixes, in the order **live-tokens-fix-findings** would take
73
- them: migrations, then the largest group of errors, then the rest, then
74
- warnings. Mark each as mechanical or judgement.
48
+ 6. Recommended fixes, in the order **live-tokens-fix-findings** would take them: migrations, then the largest group of errors, then the rest, then warnings. Mark each as mechanical or judgement.
75
49
 
76
- End with the hand-off: "Run live-tokens-fix-findings to apply these", or the
77
- subset the user chooses. Do not start applying them here, even when the fix is
78
- one line, because the user asked how things stand.
50
+ End with the hand-off: "Run live-tokens-fix-findings to apply these", or the subset the user chooses.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: live-tokens-create-component
3
- description: Author a brand-new editable component for a @motion-proto/live-tokens project when nothing in the shipped catalogue fits runtime and editor Svelte files, registration, naming, state model, and verification. Use when the user asks to author, create, or build a new tokenized component; make an existing Svelte component editable in the live-tokens editor; add a component to the catalogue; register a custom component with the editor; or build a [Thing] component that does not exist in the shipped set. Not for placing an existing shipped component on a page (see live-tokens-build-page); read live-tokens-pick-component first to confirm nothing in the catalogue fits.
3
+ description: Author a brand-new editable component for a @motion-proto/live-tokens project when nothing in the shipped catalogue fits: runtime and editor Svelte files, registration, naming, state model, and verification. Use when the user asks to author, create, or build a new tokenized component; make an existing Svelte component editable in the live-tokens editor; add a component to the catalogue; register a custom component with the editor; or build a [Thing] component that does not exist in the shipped set. Not for placing an existing shipped component on a page (see live-tokens-build-page); read live-tokens-pick-component first to confirm nothing in the catalogue fits.
4
4
  ---
5
5
 
6
6
  # Authoring a component for a live-tokens project
@@ -9,22 +9,23 @@ The end state is a runtime Svelte file, an editor Svelte file, one registration,
9
9
 
10
10
  ## Worked examples ship inside the package
11
11
 
12
- For pattern reference, read any shipped component's source directly from the consumer's `node_modules`:
12
+ Read a shipped component's source from the consumer's `node_modules` rather than from memory, because the files are the contract and this skill is not:
13
13
 
14
14
  - Runtime files: `node_modules/@motion-proto/live-tokens/src/system/components/<Name>.svelte`.
15
15
  - Simplest reads (no state, no linked-block): `Card` (single variant with parts), `Badge` and `Callout` (multi-variant).
16
16
  - Multi-state (hover, disabled, focus): `Button`, `Input`.
17
17
  - Multi-part (overlay / header / body / footer): `Dialog`.
18
18
  - Multi-variant with linked siblings (`canBeLinked` + `groupKey`): `SegmentedControl`, `TabBar`. Composes another shipped component: `CodeSnippet`.
19
- - Editor files: `node_modules/@motion-proto/live-tokens/src/editor/component-editor/<Name>Editor.svelte`.
19
+ - Every rule below in the fewest lines: `Toggle`. Component states name themselves in the token (`--toggle-on-*`, `--toggle-disabled-*`), interaction states layer on top (`--toggle-hover-*`, `--toggle-on-hover-*`), disabled is terminal (no `--toggle-disabled-hover-*`), and each `:hover` selector has a `.force-hover` sibling so the editor's preview can paint hover tokens without a pointer.
20
+ - Editor files: `node_modules/@motion-proto/live-tokens/src/editor/component-editor/<Name>Editor.svelte`. `ToggleEditor` has no `groupKey` and no `canBeLinked`; for components that share base properties across variants, read `references/linked-siblings.md`.
20
21
 
21
- **File-location note.** Shipped editors live in `src/editor/component-editor/` because they're library-internal. For *your* component, **co-locate** both files in `src/system/components/`. Read the shipped files for pattern, ignore their location.
22
+ Shipped editors live in `src/editor/component-editor/` because they are library-internal. For *your* component, co-locate both files in `src/system/components/`. Read the shipped files for pattern, ignore their location.
22
23
 
23
24
  ## The recipe
24
25
 
25
- 1. **Runtime file** `src/system/components/MyWidget.svelte`. Declare every editable slot as a CSS custom property inside `:global(:root)`, defaulting to a theme token (never a raw value). The plugin parses `:global(:root)` to seed `component-configs/<id>/default.json`; variables declared anywhere else can't be edited.
26
- 2. **Editor file** `src/system/components/MyWidgetEditor.svelte`. In a `<script module>` block, declare `const component = 'mywidget'`, build a `states: Record<string, Token[]>` for each VariantGroup, and export the flat union as `allTokens: Token[]`. Components with linked siblings also build a `linkableContexts: Map<string, string>` (read `references/linked-siblings.md`). Components with structural/display controls that aren't token values (alignment, element visibility, layout position) also export an `intrinsics: IntrinsicSpec[]` (read `references/intrinsics.md`). In the runtime `<script>` block, mount `ComponentEditorBase` with one `VariantGroup` per variant.
27
- 3. **Register** pass the component to `bootLiveTokens` in `src/main.ts`. This is the standard boot the scaffold generates and the README documents; `bootLiveTokens` calls `registerComponent` internally at the right point — after its editor init hooks (`cssVarSync.init`, `editorStore.init`), before it seeds configs and mounts the app:
26
+ 1. **Runtime file**, `src/system/components/MyWidget.svelte`. Declare every editable slot as a CSS custom property inside `:global(:root)`, defaulting to a theme token (never a raw value). The plugin parses `:global(:root)` to seed `component-configs/<id>/default.json`; variables declared anywhere else cannot be edited.
27
+ 2. **Editor file**, `src/system/components/MyWidgetEditor.svelte`. In a `<script module>` block, declare `const component = 'mywidget'`, build a `states: Record<string, Token[]>` for each VariantGroup, and export the flat union as `allTokens: Token[]`. Components with linked siblings also build a `linkableContexts: Map<string, string>` (read `references/linked-siblings.md`). Components with structural or display controls that are not token values (alignment, element visibility, layout position) also export an `intrinsics: IntrinsicSpec[]` (read `references/intrinsics.md`). In the runtime `<script>` block, mount `ComponentEditorBase` with one `VariantGroup` per variant.
28
+ 3. **Register** by passing the component to `bootLiveTokens` in `src/main.ts`, the boot the scaffold generates:
28
29
  ```ts
29
30
  import { bootLiveTokens } from '@motion-proto/live-tokens';
30
31
  import App from './App.svelte';
@@ -41,41 +42,16 @@ For pattern reference, read any shipped component's source directly from the con
41
42
  }],
42
43
  });
43
44
  ```
44
- The schema side-effect happens inside `registerComponent` (which `bootLiveTokens` calls for you), so you don't call `registerComponentSchema` separately. **Do not place a standalone `registerComponent(...)` *before* `bootLiveTokens`** that registers before the editor's init hooks run, which is the wrong window and can leave editor changes disconnected from the live page. Only call `registerComponent` directly if your app mounts manually (no `bootLiveTokens`), in which case call it before `mount(App, ...)`.
45
- 4. **Say what it is for.** The runtime file's leading HTML comment is the
46
- component's description. `npx live-tokens components` prints it beside the
47
- id with the variants and props read from `interface Props` (`--json` for
48
- data); that is how **live-tokens-pick-component** weighs a project's own
49
- component against the shipped set, so no skill file is edited and nothing
50
- is lost when `setup-claude` refreshes the skills. Name the job it does and
51
- what it is not for. A directory other than `src/system/components` goes in
52
- `"componentDirs"` in `live-tokens.config.json`; a first-party component is
53
- also added to the picker's **Catalogue** line, which `check:skills` holds.
54
- 5. **Join the sketch layer** — the effect draws a fixed set of parts, so a new
55
- component stays crisp while the page around it goes hand-drawn until it opts
56
- in. A consumer component carries one of four reserved classes on its root and
57
- names the five `--sketch-*` values it is drawn with; a first-party component
58
- adds a `PartSpec` row instead. The layer also takes `background`,
59
- `border-color`, `box-shadow`, `overflow`, `position` and both pseudo-elements
60
- away from the element it draws, which constrains where the class can go. Read
61
- `references/sketch-mode.md`.
62
- 6. **Gate on the checker.** Run it, fix every error, and run it again. Do not
63
- call the component done while it reports one:
45
+ `bootLiveTokens` calls `registerComponent` for you after its editor init hooks and before it seeds configs, so a standalone `registerComponent(...)` placed *before* `bootLiveTokens` lands in the wrong window and can leave editor changes disconnected from the live page. Call `registerComponent` directly only when the app mounts manually, and then before `mount(App, ...)`. Registering against a built-in id wins with a console warning; the right call is a unique id.
46
+ 4. **Say what it is for.** The runtime file's leading HTML comment is the component's description. `npx live-tokens components` prints it beside the id with the variants and props read from `interface Props` (`--json` for data), which is how **live-tokens-pick-component** weighs a project's own component against the shipped set: no skill file is edited, and nothing is lost when `setup-claude` refreshes the skills. Name the job it does and what it is not for. A directory other than `src/system/components` goes in `"componentDirs"` in `live-tokens.config.json`. A first-party component is also added to the picker's **Catalogue** line, which `check:skills` holds.
47
+ 5. **Join the sketch layer.** The effect draws a fixed set of parts, so a new component stays crisp while the page around it goes hand-drawn until it opts in. A consumer component carries one of four reserved classes on its root and names the five `--sketch-*` values it is drawn with; a first-party component adds a `PartSpec` row instead. The layer also takes `background`, `border-color`, `box-shadow`, `overflow`, `position` and both pseudo-elements away from the element it draws, which constrains where the class can go. Read `references/sketch-mode.md`.
48
+ 6. **Gate on the checker.** Run it, fix every error, and run it again. Do not call the component done while it reports one:
64
49
  ```bash
65
50
  npx live-tokens check-component <id> --strict --json
66
51
  ```
67
- `--json` gives each finding a stable `rule` id and a line number, so work one
68
- rule at a time and re-run rather than guessing. `--strict` fails on warnings
69
- too, which is the right setting for a new component: every warning it raises
70
- is a naming or token decision that is cheaper to make now than to migrate
71
- later. Exit code 0 is the gate. With no id it checks every component under
72
- `src/system/components`; a project scaffolded by `create` runs that as
73
- `npm run check:design` before every `vite build`.
74
-
75
- If it rejects a suffix, do not invent a new name for the role. Find a shipped
76
- component that paints the same thing and use the name it uses: the catalogue
77
- is the worked reference, and `bin/check-component.test.ts` holds all 26 of
78
- them to this same contract.
52
+ `--json` gives each finding a stable `rule` id and a line number, so work one rule at a time. `--strict` fails on warnings too, the right setting for a new component: every warning is a naming or token decision that is cheaper to make now than to migrate later. Exit code 0 is the gate. With no id it checks every component under `src/system/components`; a project scaffolded by `create` runs that as `npm run check:design` before every `vite build`.
53
+
54
+ If it rejects a suffix, do not invent a new name for the role. Find a shipped component that paints the same thing and use the name it uses: every shipped component passes this same check, so the catalogue is the worked reference.
79
55
  7. **Verify** with the checklist at the bottom of this file, then place the component on a page with **live-tokens-build-page**.
80
56
 
81
57
  ## Token discipline
@@ -86,11 +62,11 @@ For pattern reference, read any shipped component's source directly from the con
86
62
  --<componentId>-<part|variant>[-<state>][-<element>]-<property>
87
63
  ```
88
64
 
89
- - `componentId` the literal id passed to `registerComponent()`. Lowercase, no dashes, no abbreviations (`segmentedcontrol` not `sc`). The file id matches: `MyWidget.svelte` id `mywidget`.
90
- - `part` or `variant` the sub-region (`bar`, `option`, `track`, `header`, `body`, `footer`, `overlay`, `value`, `label`), or, on a component whose variants differ in more than one property, the variant name: `--badge-accent-surface`, `--callout-danger-border`. A component with both stacks them outer to inner, so the bar in its small size is `--segmentedcontrol-bar-small-padding`.
91
- - `state` (optional) interaction or component state (`hover`, `disabled`, `selected`, `focus`). **Always before the property.**
92
- - `element` (optional) sub-element inside the part (`dot`, `icon`, `label`, `text`).
93
- - `property` theme role or CSS property. Always last.
65
+ - `componentId`: the literal id passed to `registerComponent()`. Lowercase, no dashes, no abbreviations (`segmentedcontrol` not `sc`). The file id matches: `MyWidget.svelte` is id `mywidget`.
66
+ - `part` or `variant`: the sub-region (`bar`, `option`, `track`, `header`, `body`, `footer`, `overlay`, `value`, `label`), or, on a component whose variants differ in more than one property, the variant name: `--badge-accent-surface`, `--callout-danger-border`. A component with both stacks them outer to inner, so the bar in its small size is `--segmentedcontrol-bar-small-padding`.
67
+ - `state` (optional): interaction or component state (`hover`, `disabled`, `selected`, `focus`). **Always before the property.**
68
+ - `element` (optional): sub-element inside the part (`dot`, `icon`, `label`, `text`).
69
+ - `property`: theme role or CSS property. Always last.
94
70
 
95
71
  ### Suffix vocabulary
96
72
 
@@ -121,12 +97,12 @@ control behind it.
121
97
  ### Rules that bite
122
98
 
123
99
  - **Fixed overlays must portal to `<body>`.** Any `position: fixed` layer is trapped by a transformed or `contain`ed ancestor, which real pages and the editor's preview pane both have. `check:overlay-portal` fails the build without it. Read `references/fixed-overlays.md` before authoring a modal, lightbox, or backdrop.
124
- - **State before property.** `--mywidget-button-hover-surface` `--mywidget-button-surface-hover` ✗ (breaks sibling matching). Disabled is terminal in the name too: `-disabled-hover-` and `-selected-disabled-` describe states that never paint, and `check-component` rejects both.
125
- - **Every default resolves to a theme token.** A component token names a semantic property; its default is the theme token that property reads. That is what makes the component repaint when the theme changes. `var(--surface-primary)` ✓, `#6a4ce8` ✗, `white` ✗, and `var(--surface-imaginary)` ✗: `check-component` fails on a colour literal in any notation, on a `var()` naming a token that does not exist, and on a default with no token behind it at all, so a raw `16rem` fails too. Composing tokens counts and is common: `color-mix(in srgb, var(--surface-neutral-lower) 70%, transparent)`, or `calc(var(--space-64) * 4)` for a width the spacing scale does not reach. The one value allowed without a token is a structural keyword (`contain`, `start`, `none`), and only when the editor declares it in `intrinsics`.
126
- - **No abbreviations.** `bg` `surface`; `fg` `text`; component ids are never abbreviated.
100
+ - **State before property.** `--mywidget-button-hover-surface` passes; `--mywidget-button-surface-hover` breaks sibling matching. Disabled is terminal in the name too: `-disabled-hover-` and `-selected-disabled-` describe states that never paint, and `check-component` rejects both.
101
+ - **Every default resolves to a theme token.** A component token names a semantic property; its default is the theme token that property reads, which is what makes the component repaint when the theme changes. `var(--surface-primary)` passes; `#6a4ce8`, `white`, `var(--surface-imaginary)`, and a bare `16rem` all fail, because `check-component` rejects a colour literal in any notation, a `var()` naming a token that does not exist, and a default with no token behind it. Composing tokens counts and is common: `color-mix(in srgb, var(--surface-neutral-lower) 70%, transparent)`, or `calc(var(--space-64) * 4)` for a width the spacing scale does not reach. The one value allowed without a token is a structural keyword (`contain`, `start`, `none`), and only when the editor declares it in `intrinsics`.
102
+ - **No abbreviations.** `bg` is `surface`; `fg` is `text`; component ids are never abbreviated.
127
103
  - **Text aliases.** Neutral scale is `--text-primary` / `--text-secondary` / `--text-tertiary` / `--text-muted` / `--text-disabled`. Family-tinted is `--text-primary-color`, `--text-accent`, `--text-success`. There is no `--text-neutral`.
128
- - **Typography `groupKey` on multi-slot components must include the slot prefix.** `groupKey: 'value-font-family'` and `groupKey: 'label-font-family'` bare `groupKey: 'font-family'` silently merges them into one link tree ✗. Single-slot components can use a bare typography `groupKey`; add the slot prefix the moment a second slot appears. The same trap applies to type-group **colors** (two slots ending in `-text` collapsing to one `text` key). Let the helpers handle both, below.
129
- - **Let the type-group helpers derive slot-scoped keys; never rely on the bare last-dash default.** When you build typography tokens with `buildTypeGroupColorTokens` / `buildTypeGroupTokens` / `buildTypeGroupFontTokens`, **pass `{ component, variants }`** so each slot gets a distinct, structural `groupKey`:
104
+ - **Typography `groupKey` on multi-slot components must include the slot prefix.** `groupKey: 'value-font-family'` and `groupKey: 'label-font-family'` stay distinct; a bare `groupKey: 'font-family'` silently merges the slots into one link tree. Single-slot components can use a bare typography `groupKey`; add the slot prefix the moment a second slot appears. The same trap applies to type-group colours (two slots ending in `-text` collapsing to one `text` key).
105
+ - **Let the type-group helpers derive slot-scoped keys.** When you build typography tokens with `buildTypeGroupColorTokens` / `buildTypeGroupTokens` / `buildTypeGroupFontTokens`, pass `{ component, variants }` so each slot gets a distinct, structural `groupKey`:
130
106
 
131
107
  ```ts
132
108
  // variants = the variant/state segment strings as they appear in the variable name
@@ -135,24 +111,23 @@ control behind it.
135
111
  ...buildTypeGroupFontTokens(typeGroups, { component, variants: [...VARIANTS] }),
136
112
  ```
137
113
 
138
- The helper strips the `--<component>-` prefix and those segments, keeping the rest: `--mywidget-header-default-text` `header-text`, `--mywidget-header-default-text-font-family` `header-text-font-family`. Two parts ending in the same word stay distinct; one slot across variants collapses to one key. To override a single derived key, set `colorGroupKey` on that type-group config it wins and is never recomputed, so your fix survives. There is no name-based fallback: a bare `buildTypeGroupColorTokens` call emits un-grouped (solo) colors rather than guessing, and a bare *font* helper across multiple slots is a `check-component` warning (its default `font-family`/… keys would merge the slots' fonts).
139
-
114
+ The helper strips the `--<component>-` prefix and those segments, keeping the rest: `--mywidget-header-default-text` becomes `header-text`, and `--mywidget-header-default-text-font-family` becomes `header-text-font-family`. Two parts ending in the same word stay distinct; one slot across variants collapses to one key. To override a single derived key, set `colorGroupKey` on that type-group config; it wins and is never recomputed. There is no name-based fallback: a bare `buildTypeGroupColorTokens` call emits un-grouped (solo) colours rather than guessing, and a bare *font* helper across multiple slots is a `check-component` warning, because its default keys would merge the slots' fonts.
140
115
 
141
116
  ## State model
142
117
 
143
- Components *can* have two state axes. Many don't: container and messaging components (Card, Badge, Callout, CollapsibleSection) have only variants, no hover/disabled. Skip the rest of this section for those.
118
+ Components *can* have two state axes. Many do not: container and messaging components (Card, Badge, Callout, CollapsibleSection) have only variants, no hover or disabled. Skip the rest of this section for those.
144
119
 
145
- When a component does have states, don't mix the two axes:
120
+ When a component does have states, keep the two axes apart:
146
121
 
147
- - **Component states** mutually exclusive top-level fieldsets: `default`, `selected`, `disabled` (names vary by component). One fieldset per component state.
148
- - **Interaction states** a select *inside* each component-state fieldset: `default`, `hover`. Add `focus`/`active` later if needed.
122
+ - **Component states** are mutually exclusive top-level fieldsets: `default`, `selected`, `disabled` (names vary by component). One fieldset per component state.
123
+ - **Interaction states** are a select *inside* each component-state fieldset: `default`, `hover`. Add `focus` or `active` later if needed.
149
124
 
150
125
  Rules:
151
126
 
152
- - **Disabled is terminal.** A disabled component can't be hovered or focused. The `disabled` fieldset is flat no interaction selector.
153
- - **`selected-disabled` is impossible.** Don't author tokens or fieldsets for it.
154
- - **Parts states.** Dialog's `overlay | header | body | footer` are *parts* (all present simultaneously), not states. The VariantGroup tab strip defaults its label to "Element" (neutral). If you label tabs anywhere, use **part** for structure and **state** for runtime conditions. Never call a footer a state.
155
- - **Don't call interaction states "option states" or "selected states"** in the UI. `selected` is a *component* state.
127
+ - **Disabled is terminal.** A disabled component cannot be hovered or focused. The `disabled` fieldset is flat, with no interaction selector.
128
+ - **`selected-disabled` is impossible.** Do not author tokens or fieldsets for it.
129
+ - **Parts are not states.** Dialog's `overlay | header | body | footer` are *parts* (all present at once), not states. The VariantGroup tab strip defaults its label to "Element" (neutral). If you label tabs anywhere, use **part** for structure and **state** for runtime conditions. Never call a footer a state.
130
+ - **Do not call interaction states "option states" or "selected states"** in the UI. `selected` is a *component* state.
156
131
 
157
132
  Token naming consequence:
158
133
 
@@ -161,14 +136,14 @@ Token naming consequence:
161
136
  --mywidget-option-disabled-surface ✗ implies disabled is an interaction state
162
137
  --mywidget-option-hover-surface ✓ default-component-state, hover-interaction
163
138
  --mywidget-selected-hover-surface ✓ selected-component-state, hover-interaction
164
- --mywidget-selected-disabled-text ✗ selected-disabled doesn't exist
139
+ --mywidget-selected-disabled-text ✗ selected-disabled does not exist
165
140
  ```
166
141
 
167
142
  ## User-facing copy
168
143
 
169
- Strings you author for the editor UI use periods and commas, never em-dashes. Em-dashes read as an AI tell. This applies to `title=` and `description=` on `ComponentEditorBase`, token row labels, info popovers, and any text inside `previewActions` / `canvasToolbarExtras` snippets. Code comments are unaffected.
144
+ Strings you author for the editor UI use periods and commas, never em-dashes, which read as an AI tell. This applies to `title=` and `description=` on `ComponentEditorBase`, token row labels, info popovers, and any text inside `previewActions` / `canvasToolbarExtras` snippets. Code comments are unaffected.
170
145
 
171
- If you add custom chrome inside an editor snippet (rare `ComponentEditorBase` and `VariantGroup` carry the standard chrome), keep it greyscale (no accent colors) and reference heading sizes via `--ui-font-size-md` / `-lg` / `-2xl` rather than pixel literals.
146
+ Custom chrome inside an editor snippet is rare, since `ComponentEditorBase` and `VariantGroup` carry the standard chrome. Where you add some, keep it greyscale (no accent colours) and reference heading sizes via `--ui-font-size-md` / `-lg` / `-2xl` rather than pixel literals.
172
147
 
173
148
  ## Public imports only
174
149
 
@@ -187,26 +162,6 @@ That covers everything the worked examples use. Additional primitives (`LinkedBl
187
162
 
188
163
  **Never deep-import `node_modules/@motion-proto/live-tokens/src/...`.** Reading those files for pattern reference is fine; importing them at runtime is not. If you need something not exported, file an issue rather than reaching in.
189
164
 
190
- ## Worked example: the shipped Toggle
191
-
192
- Toggle exercises every rule above in the fewest lines. Read both files from the package rather than from memory, because they are the contract and this skill is not:
193
-
194
- - `node_modules/@motion-proto/live-tokens/src/system/components/Toggle.svelte`
195
- - `node_modules/@motion-proto/live-tokens/src/editor/component-editor/ToggleEditor.svelte`
196
-
197
- What to notice in the runtime file:
198
-
199
- - Component states (`on`, `disabled`) name themselves in the token: `--toggle-on-*`, `--toggle-disabled-*`.
200
- - Interaction states layer on top: `--toggle-hover-*` for default+hover, `--toggle-on-hover-*` for on+hover.
201
- - Disabled is terminal: no `--toggle-disabled-hover-*`, no `--toggle-on-disabled-*`.
202
- - The `force-hover` class pairs with the editor's preview hook so hover tokens paint without a real pointer. Each `:hover` selector has a matching `.force-hover` sibling.
203
-
204
- What to notice in the editor file:
205
-
206
- - No `groupKey`, no `canBeLinked`: Toggle has no linked siblings. For components that share base properties across variants, read `references/linked-siblings.md`.
207
-
208
- For your own component, copy the pattern and substitute your id. Registering against a built-in id wins with a console warning, but the right call is a unique id.
209
-
210
165
  ## Extensions
211
166
 
212
167
  Read the sketch reference for every component; the other two only when they apply.
@@ -217,24 +172,11 @@ Read the sketch reference for every component; the other two only when they appl
217
172
 
218
173
  ## Verification checklist
219
174
 
220
- After saving, run the static validator first:
221
-
222
- ```bash
223
- npx live-tokens check-component <id>
224
- # or: npx @motion-proto/live-tokens check-component <id>
225
- ```
226
-
227
- It enforces the file layout, the `:global(:root)` block, token-suffix vocabulary, state-before-property rule, the terminal disabled state, public-imports rule, that every token an editor row names is declared in the runtime, and that the id is registered, via either `bootLiveTokens({ components: [{ id }] })` or a direct `registerComponent({ id })` call. On the value side it fails on a colour literal in any notation, on a default reading a token that does not exist, and on a default with no theme token behind it that the editor does not declare an intrinsic.
228
-
229
- It *warns* (non-fatal) when a token-backed default still carries a px or rem term, and when a type-group font helper is called bare across multiple slots, which would merge their fonts into one link tree.
230
-
231
- Exit code 0 means the static contract is met. Resolve warnings before shipping, or run with `--strict` to make them fail. `--json` prints findings with a stable `rule` id, so you can work through one rule at a time and re-run.
232
-
233
- **Then run the registry contract test.** `checkRegistryEntry`, from `@motion-proto/live-tokens/component-editor/contract`, takes one registry entry and returns a violation line per failure, so a suite over your own components is a `describe.each` and one call. Per component it verifies that the registration resolves to a real `sourceFile` and a non-empty schema, that schema variables are unique, that every editable token is declared in the runtime `<style>` block and seeded in `component-configs/<id>/default.json`, that a token declaring `minOpacity` seeds at or above its floor, and that `setComponentAlias` round-trips the alias through the slice. The test file, the two lines in it that are load-bearing, and the path options are in `references/contract-tests.md`.
175
+ Step 6 of the recipe is the static gate: `npx live-tokens check-component <id>` at exit 0, with `--strict` clean or its warnings resolved. It enforces the file layout, the `:global(:root)` block, the suffix vocabulary, state-before-property, the terminal disabled state, public imports, that every token an editor row names is declared in the runtime, that every default reads a theme token, and that the id is registered through `bootLiveTokens({ components: [{ id }] })` or a direct `registerComponent({ id })` call.
234
176
 
235
- Inside the package, `src/editor/component-editor/registryContract.test.ts` is that same file over `builtInRegistry`, so a new first-party component is auto-covered the moment it lands there — `npm test` fails if any check misses.
177
+ **Then run the registry contract test.** `checkRegistryEntry`, from `@motion-proto/live-tokens/component-editor/contract`, takes one registry entry and returns a violation line per failure, so a suite over your own components is a `describe.each` and one call. It verifies that the registration resolves to a real `sourceFile` and a non-empty schema, that schema variables are unique, that every editable token is declared in the runtime `<style>` block and seeded in `component-configs/<id>/default.json`, that a token declaring `minOpacity` seeds at or above its floor, and that `setComponentAlias` round-trips the alias through the slice. The test file and its path options are in `references/contract-tests.md`. Inside the package, `registryContract.test.ts` runs that same check over `builtInRegistry`, so a first-party component is covered the moment it lands there.
236
178
 
237
- **If your component declares `intrinsics`, the intrinsics contract test covers it too.** `src/editor/component-editor/intrinsicsContract.test.ts` iterates every entry with an `intrinsics` array and asserts, per (intrinsic, variant), that the runtime `:global(:root)` declares a default, the default is one of the spec's `values`, and the editor's `default` equals the runtime default. This is what would have caught a getter defaulting to `center` while `:global(:root)` says `start`. Same auto-coverage rule: declare `intrinsics` on the registry entry and the test picks it up.
179
+ **If your component declares `intrinsics`, the intrinsics contract test covers it too.** `intrinsicsContract.test.ts` asserts, per (intrinsic, variant), that the runtime `:global(:root)` declares a default, that it is one of the spec's `values`, and that the editor's `default` equals it. This is what would have caught a getter defaulting to `center` while `:global(:root)` says `start`.
238
180
 
239
181
  Finally navigate to `/live-tokens/components` and confirm the runtime behaviours no static check can see:
240
182
 
@@ -85,10 +85,17 @@ preview of the hover state, and a hover the sketch layer cannot paint reads as
85
85
  no hover at all once the real background is transparent.
86
86
 
87
87
  An inner part that carries its own surface (a header strip, a footer) takes its
88
- own class and its own five values. Where such a part draws no outline, bind the
88
+ own class and its own five values. The class is easy to forget, because the part
89
+ already has its own values and looks finished without it — a part carrying only
90
+ the values is left crisp, and reads as a hard-edged rectangle dropped inside a
91
+ drawn box. No checker sees it. Where such a part draws no outline, bind the
89
92
  hatch ink to the ink its **parent** is outlined in, so the component reads as one
90
93
  drawing rather than a shaded panel dropped into a box:
91
94
 
95
+ ```svelte
96
+ <span class="mywidget-header sketch-chip">{label}</span>
97
+ ```
98
+
92
99
  ```css
93
100
  .mywidget-header {
94
101
  --sketch-fill: var(--mywidget-header-surface);
@@ -3,73 +3,36 @@ name: live-tokens-fix-findings
3
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).
4
4
  ---
5
5
 
6
- # Fixing what the checkers report
7
-
8
- Two checkers hold a project to its design system. `check-page` holds pages:
9
- every component comes from the catalogue and is passed only the props it
10
- declares, and every value in page CSS is a theme token. `check-component`
11
- holds authored components: every token names a semantic property and its
12
- default is the theme token that property reads. A page or component that
13
- passes repaints when the theme changes. One that does not has opted out of the
14
- system silently, and these findings are where.
15
-
16
- This skill is the loop for code that already exists. Run the checker, fix one
17
- rule at a time, run it again, and stop only when both exit 0. When the user has
18
- not seen the state of the project yet, `npx live-tokens report --json` is the
19
- reading to start from, and **live-tokens-check-compliance** is the skill that
20
- presents it without editing; this one edits.
21
-
22
- ## Reach the checkers
23
-
24
- ```sh
25
- npx live-tokens check-page --json # every page under src/
26
- npx live-tokens check-component --json # every component authored under src/system/components
27
- ```
28
-
29
- - **Unknown command.** The installed package predates the checkers. Upgrade
30
- `@motion-proto/live-tokens`, then run `npx live-tokens migrate --check` and
31
- apply what it plans with `--write`; `--tokens <path>` names a tokens.css that
32
- sits somewhere other than the four default locations.
33
- - **No `check:design` script.** A project scaffolded by `create` has one. Add
34
- it to any other project's `package.json`:
35
- `"check:design": "live-tokens check-page && live-tokens check-component"`.
36
- Once it passes, gate the build: `"build": "npm run check:design && vite build"`.
37
- - **A file, not the project.** `check-page src/pages/Home.svelte` and
38
- `check-component <id>` scope a run when the user names one thing.
39
-
40
- ## The loop
41
-
42
- 1. Run with `--json`. Each finding carries a stable `rule`, a file, and a line.
43
- 2. Group by rule. Take errors before warnings, and the rule with the most
44
- findings first, because one recipe clears the whole group.
45
- 3. Apply that rule's recipe, below, to every finding in the group.
46
- 4. Run again. New findings can appear as old ones clear: a token you reached
47
- for may not exist, or a moved import may land somewhere the rule now sees.
48
- 5. Stop at exit 0. Then run once with `--strict` and report what it adds, so
49
- the user can decide whether warnings are worth clearing now.
50
-
51
- Three things the loop never does:
52
-
53
- - **Silence a rule to pass.** `--off=<rule>` is for a single run while
54
- working. A severity the project wants changed goes in
55
- `live-tokens.config.json` under `"checks": { "rules": { "<rule>": "warn" } }`,
56
- with the reason in the commit, and only when the user has made that call.
57
- - **Mint a token.** A literal with no token behind it is remapped to the
58
- nearest existing token by role. No new `--surface-*`, `--text-*`, or
59
- `--space-*` is added to `tokens.css` to match a value the page happened to
60
- use. If nothing fits, say so and leave the finding.
61
- - **Change what the page looks like without saying so.** Most remaps land on
62
- the same value. When the nearest token differs, `14px` to `--space-16` or a
63
- 55% black to `--scrim`, name the shift in the report.
6
+ # Fixing the checkers' findings
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.
11
+
12
+ ## Workflow
13
+
14
+ 1. Run both checkers with `--json`. Each finding carries a stable `rule`, a file, and a line.
15
+ ```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
18
+ ```
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.
24
+
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"`.
26
+
27
+ ## Three things the loop never does
28
+
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.
64
32
 
65
33
  ## Colour by role, never by hue
66
34
 
67
- `color-literal` is the finding that takes judgement. The replacement is the
68
- token for what the colour *does*, not the token that happens to be closest in
69
- hue, because the theme will move every role together and the page must move
70
- with it. `npx live-tokens tokens --family surface` prints a family's names and
71
- values (`text`, `border`, `scrim`, `tint` likewise; `--json` for data); the
72
- families are fixed.
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.
73
36
 
74
37
  | The literal is | Token family | Notes |
75
38
  | --- | --- | --- |
@@ -82,15 +45,11 @@ families are fixed.
82
45
  | Fully transparent | `--color-transparent` | Never `transparent` inside a component default. |
83
46
  | A gradient | `--gradient-*` | Or compose one from surface tokens. |
84
47
 
85
- A `var(--x, #fff)` fallback is not a finding. A named colour is: `white` and
86
- `rebeccapurple` are literals like any hex.
48
+ A `var(--x, #fff)` fallback is not a finding. A named colour is: `white` and `rebeccapurple` are literals like any hex.
87
49
 
88
50
  ## Geometry by scale
89
51
 
90
- `dimension-literal` fires only on the geometry the theme owns: padding,
91
- margin, gap, border and outline widths, inset offsets, radius, and shadow.
92
- Sizing (a hero's height, a max content width, a `minmax()` floor) is layout
93
- and is never reported, so leave it.
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.
94
53
 
95
54
  | The literal is | Token | Notes |
96
55
  | --- | --- | --- |
@@ -100,8 +59,7 @@ and is never reported, so leave it.
100
59
  | A shadow | `--shadow-sm` through `-xl` | Replace the whole value, never one offset. |
101
60
  | Part of a `calc()` | The token inside the calc | `calc(var(--space-64) * -2 + var(--space-8))` |
102
61
 
103
- While in the file, motion values take `--duration-*` and `--ease-*` even
104
- though no rule reports them, and a `blur()` takes `--blur-*`.
62
+ While in the file, motion values take `--duration-*` and `--ease-*` even though no rule reports them, and a `blur()` takes `--blur-*`.
105
63
 
106
64
  ## Every other rule
107
65
 
@@ -120,17 +78,12 @@ though no rule reports them, and a `blur()` takes `--blur-*`.
120
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**. |
121
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`. |
122
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. |
123
- | `missing-registration`, `missing-file`, `missing-root-block` | The component is not wired the way the recipe in **live-tokens-create-component** wires it. |
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. |
124
82
 
125
83
  ## Report
126
84
 
127
- Say what changed by rule, one line per rule with the count and any visible
128
- shift. Say what was left and why, with the config entry if the user chose to
129
- lower a severity. End with the two commands and their exit codes.
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.
130
86
 
131
87
  ## Verify
132
88
 
133
- Open `/live-tokens/editor` in dev and change a surface colour and a spacing
134
- step. Every file the loop touched should repaint. One that does not still
135
- holds a literal the checker cannot see, which is worth reporting as a gap in
136
- the checker rather than patching around.
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.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: live-tokens-generate-theme
3
- description: Generate a complete live-tokens theme color, type, and geometry from a natural-language brief, delegating the type and geometry halves to its sibling skills. Use whenever the user asks for a theme, look, vibe, brand feel, color scheme, or palette by mood, style, era, season, holiday, or hue; when they name only a color (something red-based, green and gold for St. Patrick's Day); or when they refine an existing theme (warmer, more contrast, calmer). Examples: bright and cheerful, dark and moody, brutalist, mid-century modern, Swiss and minimal, cyberpunk neon, editorial magazine, make it feel like a terminal. Not for a single token (use the editor), type alone (live-tokens-pair-fonts), or geometry alone (live-tokens-adjust-geometry).
3
+ description: Generate a complete live-tokens theme (color, type, and geometry) from a natural-language brief, delegating the type and geometry halves to its sibling skills. Use whenever the user asks for a theme, look, vibe, brand feel, color scheme, or palette by mood, style, era, season, holiday, or hue; when they name only a color (something red-based, green and gold for St. Patrick's Day); or when they refine an existing theme (warmer, more contrast, calmer). Examples: bright and cheerful, dark and moody, brutalist, mid-century modern, Swiss and minimal, cyberpunk neon, editorial magazine, make it feel like a terminal. Not for a single token (use the editor), type alone (live-tokens-pair-fonts), or geometry alone (live-tokens-adjust-geometry).
4
4
  ---
5
5
 
6
6
  # Generating a theme from a brief
@@ -145,7 +145,7 @@ This table is the fallback. When the brief matched an entry in the mood or style
145
145
 
146
146
  One adjective moves one dial. Warmer and cooler rotate hue; calmer and louder move chroma; lighter, darker, and moodier move Canvas L and the scheme; more contrast widens the L gap between Canvas and Brand and takes chroma out of the ground rather than adding it to the garnish. Leave every seed the user did not name alone, because a refinement that re-rolls the whole palette reads as a different theme and loses the thing they liked.
147
147
 
148
- ## What each step writes
148
+ ## Files each step writes
149
149
 
150
150
  Color writes `themes/<slug>.json` and opens it. Type and geometry write the unsaved buffers, which the page already runs. One Save in the editor keeps all three; Adopt ships them. Component aliases and gradients carry forward from the live look into a generated theme; user-tuned gradients survive, stock ones rebuild from the new families.
151
151
 
@@ -63,7 +63,7 @@ All four pick one option from a set. The right one depends on **option count**,
63
63
  | `Dialog` | Modal, blocks page | Confirmations, focused tasks the page can't continue around |
64
64
  | `Panel` | Inline, fixed stage | A demo or preview surface whose height must not reflow |
65
65
 
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.
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
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
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
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`.
@@ -83,7 +83,7 @@ All four pick one option from a set. The right one depends on **option count**,
83
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
84
  - `Badge` and `CornerBadge` differ only in positioning. `CornerBadge` lives at a `top-right` / `bottom-left` anchor on a parent (notification counts, "NEW" stickers).
85
85
 
86
- ## Display family: what the page shows rather than what it asks
86
+ ## Display family: shown, not asked
87
87
 
88
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
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.
@@ -108,4 +108,4 @@ All three can express a binary choice. The right one depends on what the choice
108
108
 
109
109
  ---
110
110
 
111
- If nothing in the catalogue fits (a `Slider`, 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.
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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,37 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.72.1 — The compliance skills have a spine
4
+
5
+ ### Changed
6
+
7
+ - **`live-tokens-check-compliance` and `live-tokens-fix-findings` open with a
8
+ numbered workflow**, the same spine the other six skills have: run the
9
+ command, read the result, apply the recipe, re-run, hand off. Both were
10
+ prose-first, so a reader (and the Skill Atlas that draws them) had no steps,
11
+ no gate, and no hand-off to find. fix-findings now also covers the four
12
+ wiring rules its table skipped (`invalid-id`, `no-tokens`,
13
+ `missing-component-const`, `missing-all-tokens`).
14
+
15
+ - **`live-tokens-create-component` is 189 lines, down from 247.** The
16
+ standalone Toggle walkthrough is folded into the worked-examples list, the
17
+ verification checklist no longer restates the checker step, and the
18
+ registration caveat is shorter. Nothing a consumer needs to author a
19
+ component was removed.
20
+
21
+ - **The sketch reference's inner-part example carries its reserved class.**
22
+ The prose said a drawn part takes its own class and its own five
23
+ `--sketch-*` values; the code under it showed only the CSS, so a part
24
+ authored from the example was left crisp inside a drawn box.
25
+
26
+ ### Fixed
27
+
28
+ - **`live-tokens-build-page` no longer promises a Cmd+G shortcut.** There is
29
+ none; the columns overlay is the vertical-lines button in the overlay's
30
+ header.
31
+
32
+ - **`live-tokens-pick-component` no longer lists `Slider` as a component the
33
+ catalogue lacks.** It shipped in 0.71.0.
34
+
3
35
  ## 0.72.0 — The contract a consumer can run
4
36
 
5
37
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@motion-proto/live-tokens",
3
- "version": "0.72.0",
3
+ "version": "0.72.1",
4
4
  "type": "module",
5
5
  "description": "Design token editor with live CSS variable editing. Svelte 5 + Vite 8.",
6
6
  "keywords": [