@motion-proto/live-tokens 0.91.2 → 0.92.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 (46) hide show
  1. package/.claude/skills/live-tokens-create-page/SKILL.md +10 -3
  2. package/.claude/skills/live-tokens-set-type/SKILL.md +3 -3
  3. package/CHANGELOG.md +140 -0
  4. package/bin/lib/tokenVocabulary.mjs +2 -2
  5. package/bin/rules/testRuns.mjs +1 -1
  6. package/bin/rules/tokens.mjs +3 -3
  7. package/dist-plugin/chunk-JOSSYGR2.js +1634 -0
  8. package/dist-plugin/index.cjs +932 -15
  9. package/dist-plugin/index.js +1 -1
  10. package/dist-plugin/setType/index.cjs +23 -2
  11. package/dist-plugin/setType/index.js +23 -2
  12. package/dist-plugin/tokensCssMigrations/index.cjs +936 -15
  13. package/dist-plugin/tokensCssMigrations/index.d.cts +23 -3
  14. package/dist-plugin/tokensCssMigrations/index.d.ts +23 -3
  15. package/dist-plugin/tokensCssMigrations/index.js +5 -1
  16. package/package.json +1 -1
  17. package/src/app/site.css +243 -9
  18. package/src/demo/TestingLoops.svelte +9 -9
  19. package/src/editor/core/fonts/weightCoverage.ts +31 -2
  20. package/src/editor/core/palettes/tokenRegistry.ts +36 -37
  21. package/src/editor/core/themes/parsers/mediaBlocks.ts +46 -0
  22. package/src/editor/core/typeScale/typeScale.ts +341 -0
  23. package/src/editor/skill-atlas/SourcePane.svelte +3 -3
  24. package/src/editor/skill-atlas/skillSources.generated.ts +2 -2
  25. package/src/editor/skill-atlas/trees/create-page.ts +14 -14
  26. package/src/editor/skill-atlas/trees/set-type.ts +2 -2
  27. package/src/editor/ui/UIFontFamilySelector.svelte +5 -1
  28. package/src/editor/ui/UIFontWeightSelector.svelte +4 -0
  29. package/src/editor/ui/UILetterSpacingSelector.svelte +4 -0
  30. package/src/editor/ui/UILineHeightSelector.svelte +4 -0
  31. package/src/editor/ui/UITextTransformSelector.svelte +4 -0
  32. package/src/editor/ui/UIVariantSelector.svelte +6 -8
  33. package/src/editor/ui/VariablesTab.svelte +4 -4
  34. package/src/editor/ui/sections/textStyles.ts +44 -92
  35. package/src/editor/ui/text-styles/ControlBody.svelte +100 -0
  36. package/src/editor/ui/text-styles/ResetIcon.svelte +60 -0
  37. package/src/editor/ui/text-styles/StepRow.svelte +330 -0
  38. package/src/editor/ui/text-styles/StyleControl.svelte +128 -0
  39. package/src/editor/ui/text-styles/TextStylesSection.svelte +551 -0
  40. package/src/editor/ui/text-styles/textStyleEdits.ts +308 -0
  41. package/src/editor/ui/variantScales.ts +16 -0
  42. package/src/system/styles/tokens.css +412 -48
  43. package/src/testing-js/page-compliance.contract.js +233 -80
  44. package/src/testing-js/page-compliance.contract.js.map +1 -1
  45. package/dist-plugin/chunk-GWMEYBZ2.js +0 -715
  46. package/src/editor/ui/TextStylesSection.svelte +0 -171
@@ -79,7 +79,7 @@ Show related items side by side when the width permits. A line of copy runs 45 t
79
79
  - 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.
80
80
  - Text inside a `Card` or a `CollapsibleSection` takes the container's type on nested `p`, `ul`, `ol`, and `li`. When the page owns that type, as full-bleed media does, pass `prose={false}`.
81
81
  - An empty stage shows a heading that names the condition and one `secondary` Button that fills it. An error goes in a `Callout variant="danger"`.
82
- - A container in a tool UI labels itself: `Card variant="bare"` with the label in the body as `--body-sm-*` in `--text-secondary`.
82
+ - A container in a tool UI labels itself: `Card variant="bare"` with the label in the body as `.body-sm` in `--text-secondary`.
83
83
  - A row of fields is a flex row with `gap: var(--space-20)`; each field's wrapper takes `flex: 1`.
84
84
  - A toolbar is a flex row of Buttons on the section's bottom edge, with no container around it. Group the Buttons left and right with `justify-content: space-between`. A `danger` Button sits apart from the group it could be mistaken for. A vertical stack of Buttons sets `fullWidth` on each Button; a row omits it.
85
85
  - For a `MenuSelect` picker, toggle it from a Button with a trailing chevron (`icon="fa-solid fa-chevron-down" iconPosition="right"`) and position the list under the Button at `top: 100%` with a `--space-*` margin.
@@ -106,18 +106,25 @@ Show related items side by side when the width permits. A line of copy runs 45 t
106
106
 
107
107
  One text style per element. A text style has five axes: `-font-family`, `-font-size`, `-font-weight`, `-line-height`, and `-letter-spacing`. Set all five from the one style.
108
108
 
109
+ The text styles fall into five usages, each a scale of seven steps from `2xs` to `2xl`: display for type outside the page outline, heading for the outline, body for interface text and short copy, editorial for long reading, and code. Each step is a style named `--{usage}-{step}-*`, such as `--body-sm-*`. Headings use the whole set. The other usages mostly take `md` and `sm`.
110
+
109
111
  | Element | Style |
110
112
  |---|---|
111
113
  | Page title | `h1` in `--heading-xl-*` |
112
114
  | Section title | `h2` in `--heading-lg-*`, or `SectionDivider variant="sm"` |
115
+ | Title inside a section | `h3` to `h6` in `--heading-md-*` to `--heading-2xs-*` |
113
116
  | Card title | the Card `title` prop |
117
+ | Hero title | `--display-xl-*` |
118
+ | Big number | `--display-md-*` |
114
119
  | Label above a group | `--body-sm-*` in `--text-secondary` |
115
120
  | Body | `p` in `--body-md-*` |
116
121
  | Secondary line | `--body-sm-*` in `--text-secondary` |
117
122
  | Count, status, read-out | `--body-sm-*` in `--text-primary` |
118
- | Command or value | `code` in `--code-*` |
123
+ | Article copy | `p` in `--editorial-md-*` |
124
+ | Code block | `pre` in `--code-md-*` |
125
+ | Command or value in a line | `code`, at `0.875em` of the text around it |
119
126
 
120
- Use the semantic element for each place: one `h1`, an `h2` for each section, `h3` inside a section, `p` for copy. Heading levels run in order with no skipped level. `site.css` types bare `h1` to `h4`, `p`, `code`, `pre`, and list items from these styles, so the tag carries the style. Type an element only when the table gives its tag a different style. A weight alone, on `strong` or a list marker, is the one axis a page sets by itself. A page shows at most two weights.
127
+ Use the semantic element for each place: one `h1`, an `h2` for each section, `h3` inside a section, `p` for copy. Heading levels run in order with no skipped level. `site.css` types bare `h1` to `h6`, `p`, `small`, `code`, `pre`, and list items from these styles, so the tag carries the style. It also gives every step a class of the same name, such as `.display-md` or `.body-sm`, that sets all five axes. Type an element only when the table gives its tag a different style, and type it with the step's class. A weight alone, on `strong` or a list marker, is the one axis a page sets by itself. A page shows at most two weights.
121
128
 
122
129
  ### Size
123
130
 
@@ -14,7 +14,7 @@ The result is on screen as soon as the run finishes. The three set skills write
14
14
  1. Read the type intent and any anchor live-tokens-create-theme passed. When either names an anchor (a feeling, an idiom, or a genre), read its entry in `references/type-anchors.md`; it overrides the Voice table below.
15
15
  2. Choose the pairing and write it to `scratch/font-pairing.json`.
16
16
  3. Run `npx live-tokens set-type scratch/font-pairing.json`. It prints each stack that moved, each family's weights and URL, and, under Weight coverage, the weights the typography tokens ask for that the family lacks.
17
- 4. Read the report. Name a missing weight and offer an alternative only when it matters: a body face without 400, 700, or italic matters, and a display face without 300 does not. A family not on Google Fonts fails the run. Fix the spelling and re-run. A pairing the stacks already hold prints "Nothing to change" and writes nothing. A pairing equal to the open theme's discards the buffer, and the report says so.
17
+ 4. Read the report. Name a missing weight and offer an alternative only when it matters: a body face without 400, 600, or italic matters, and a display face without 300 does not. A family not on Google Fonts fails the run. Fix the spelling and re-run. A pairing the stacks already hold prints "Nothing to change" and writes nothing. A pairing equal to the open theme's discards the buffer, and the report says so.
18
18
  5. Reply with the two families, the form model behind each, the matrix verdict, and any missing weight worth naming.
19
19
 
20
20
  Flags: `--dry-run` reports without writing. `--no-verify` skips the network and requires a URL per family; use it only offline.
@@ -25,13 +25,13 @@ Flags: `--dry-run` reports without writing. `--no-verify` skips the network and
25
25
  { "display": "Fraunces", "body": "Nunito Sans" }
26
26
  ```
27
27
 
28
- Every slot is optional; an omitted slot keeps its family. `display` is `--font-display` and `body` is `--font-sans`. `serif`, `mono`, and `editorial` exist when a theme needs them. `editorial` is `--font-editorial`, the long-reading face behind the `--editorial-*` text styles. An omitted `editorial` keeps its family, so set it only when essays and articles need a face of their own. Weight coverage is reported for `display`, `body`, `serif`, and `mono`. A family bound to `editorial` gets no coverage line. A slot may be `{ "name": "...", "url": "..." }` to pin a URL. A pinned URL is not probed, so the report shows no weights for it and coverage skips it. Spell families as Google does; the CLI reports the canonical spelling.
28
+ Every slot is optional; an omitted slot keeps its family. `display` is `--font-display`, the face of the display and heading usages (`--display-font-family`, `--heading-font-family`). `body` is `--font-sans`, the face of the body usage (`--body-font-family`) and of `h4` to `h6`. `mono` is `--font-mono`, the face of the code usage (`--code-font-family`). `serif` exists when a theme needs it. `editorial` is `--font-editorial`, the long-reading face behind the editorial usage (`--editorial-font-family`). An omitted `editorial` keeps its family, so set it only when essays and articles need a face of their own. Weight coverage is reported for `display`, `body`, `serif`, and `mono`. A family bound to `editorial` gets no coverage line. A slot may be `{ "name": "...", "url": "..." }` to pin a URL. A pinned URL is not probed, so the report shows no weights for it and coverage skips it. Spell families as Google does; the CLI reports the canonical spelling.
29
29
 
30
30
  ## Choose the body face first
31
31
 
32
32
  The body face is the anchor. It carries most of the words, and text faces survive small sizes where display faces do not. Pick it against the type intent, then pick the display face against it. A body face has regular, bold, and italic; low to moderate stroke contrast; open apertures; and a large x-height. A face missing any of these is a display face, whatever its name says.
33
33
 
34
- The shipped text styles ask the display face for 600 and the body face for 400; `strong` and `em` add 700 and italic. Screen candidates against those four weights before running.
34
+ The display and heading usages ask the display face for 600 through `--display-font-weight` and `--heading-font-weight`. The body usage asks the body face for 400 through `--body-font-weight`, and `h4` to `h6` ask it for 600. The code usage asks the mono face for 400 through `--code-font-weight`. `strong` asks for 600, and `em` adds italic. Screen candidates against those weights before running.
35
35
 
36
36
  ## The font matrix
37
37
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,145 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.92.0 — Type scales for text styles
4
+
5
+ ### Changed (breaking)
6
+
7
+ - **The code text style's size, leading and tracking move to its md step.**
8
+ `--code-font-size`, `--code-line-height` and `--code-letter-spacing` become
9
+ `--code-md-font-size`, `--code-md-line-height` and
10
+ `--code-md-letter-spacing`. `--code-font-family` and `--code-font-weight`
11
+ keep their names and now set the code usage's face and weight. A `site.css`
12
+ copied from an earlier release still reads the old names, and check-page
13
+ reports each one as `unknown-token`. The next entry gives the `code` and
14
+ `pre` rules that replace them.
15
+ - **Inline `code` sizes relative to its parent.** `site.css` sets `code` at
16
+ `0.875em`, so inline code in a heading grows with the heading, and
17
+ `pre code` takes the block's size. `code` and `pre` both read the code md
18
+ face, weight and letter spacing, and `pre` also reads its size and line
19
+ height. A project keeps the `code` and `pre` rules in its own copy of
20
+ `site.css` until it replaces them with these:
21
+
22
+ ```css
23
+ code {
24
+ font-family: var(--code-md-font-family);
25
+ font-size: 0.875em;
26
+ font-weight: var(--code-md-font-weight);
27
+ letter-spacing: var(--code-md-letter-spacing);
28
+ }
29
+
30
+ pre {
31
+ font-family: var(--code-md-font-family);
32
+ font-size: var(--code-md-font-size);
33
+ font-weight: var(--code-md-font-weight);
34
+ line-height: var(--code-md-line-height);
35
+ letter-spacing: var(--code-md-letter-spacing);
36
+ }
37
+
38
+ pre code {
39
+ font-size: inherit;
40
+ }
41
+ ```
42
+
43
+ - **Every text style's `-font-size` resolves per viewport.** Each step
44
+ declares a `-desktop-font-size`, a `-tablet-font-size` and a
45
+ `-phone-font-size`. Its `-font-size` keeps its name, points at the desktop
46
+ size, and `tokens.css` re-points it at 768px and 480px. A tablet or phone
47
+ size starts at `16px × (desktop size ÷ 16px) ^ compression`, capped at the
48
+ desktop size, so sizes above 16px shrink and reading sizes hold.
49
+ Set a size through its desktop, tablet or phone name: a theme that sets
50
+ `-font-size` itself outweighs the breakpoint re-points. The sizes use CSS
51
+ `pow()`, which ships in Chrome and Edge 120, Firefox 118 and Safari 15.4.
52
+ - **Heading sizes follow a major third from a 24px base.** h2 and h3 grow the
53
+ most and take distinct sizes on phones.
54
+
55
+ | Element | Desktop | Tablet | Phone |
56
+ |---|---|---|---|
57
+ | h1, `--heading-xl-font-size` | 36 → 37.5px | 30 → 30.3px | 28 → 27.4px |
58
+ | h2, `--heading-lg-font-size` | 24 → 30px | 22 → 25.6px | 20 → 23.8px |
59
+ | h3, `--heading-md-font-size` | 20 → 24px | 20 → 21.7px | 20 → 20.7px |
60
+ | h4, `--heading-sm-font-size` | 18 → 19.2px | 18 → 18.3px | 18 → 17.9px |
61
+
62
+ Body sm, editorial sm and the eyebrow move from 14px to 14.2px. Editorial
63
+ xl moves from 20px to 20.2px, and editorial lg holds 18px on desktops. On
64
+ tablets they ease to 19.1px and 17.5px, and on phones to 18.6px and 17.2px.
65
+ Body md, editorial md and code md keep their sizes.
66
+ - **Each step's face and weight read its usage's settings.**
67
+ `--heading-xl-font-family` holds `var(--heading-font-family)`, and every
68
+ other step follows the same pattern, so one edit restyles a whole usage.
69
+ Each resolves to the face and weight it had before. Heading sm, xs and 2xs
70
+ pin `var(--font-sans)`, which keeps h4 in the sans face.
71
+
72
+ ### Added
73
+
74
+ - **The display usage.** `--display-{2xs,xs,sm,md,lg,xl,2xl}-*` style type
75
+ outside the page outline, such as heroes, section titles and big numbers.
76
+ Display md is 48px on a minor third, so display xl is 69.1px.
77
+ - **Seven steps in every usage.** Display, heading, body, editorial and code
78
+ each run 2xs, xs, sm, md, lg, xl and 2xl. md is the base, each step up
79
+ multiplies by the ratio, and each step down divides by it. Heading gains
80
+ 2xl, xs and 2xs; body gains 2xl, xl, lg, xs and 2xs; editorial gains 2xl,
81
+ xs and 2xs; code gains every step beside md. The eyebrow gains a desktop, a
82
+ tablet and a phone size, which follow body sm.
83
+ - **Scale settings for each usage.** `--{usage}-font-family`,
84
+ `--{usage}-font-weight`, `--{usage}-scale-base` and `--{usage}-scale-ratio`.
85
+ The base is a unitless count of rem, and a step's desktop size is
86
+ `base × ratio ^ n`, with n from -3 at 2xs to 3 at 2xl.
87
+
88
+ | Usage | Face | Weight | Base | Ratio |
89
+ |---|---|---|---|---|
90
+ | Display | display | semibold | 3 (48px) | 1.2, minor third |
91
+ | Heading | display | semibold | 1.5 (24px) | 1.25, major third |
92
+ | Body | sans | normal | 1 (16px) | 1.125, major second |
93
+ | Editorial | editorial | normal | 1 (16px) | 1.125, major second |
94
+ | Code | mono | normal | 0.875 (14px) | 1.125, major second |
95
+
96
+ - **Compression settings.** `--type-tablet-scale-compression` (0.75) and
97
+ `--type-phone-scale-compression` (0.63) set how hard each tablet and phone
98
+ size pulls toward 16px. At 1 a viewport keeps the desktop sizes.
99
+ - **`site.css` rules for h5, h6 and `small`, and a class for every step.**
100
+ h5 reads heading xs, h6 reads heading 2xs, and `small` reads body sm. Each
101
+ of the 35 steps has a class that sets its five tokens, from `.display-2xl`
102
+ to `.code-2xs`. `create` copies the new rules into a new project. An
103
+ existing project copies them from the package's `src/app/site.css`.
104
+
105
+ ### Changed
106
+
107
+ - **The editor's Text Styles group holds a tab per usage.** A Responsive
108
+ scaling row opens the group with a tablet slider and a phone slider, each
109
+ showing its effect on 72, 48 and 24px. Each tab sets its usage's face,
110
+ weight, base and ratio, and lists its seven steps from 2xl to 2xs. A step
111
+ row shows its element, its desktop, tablet and phone sizes, a sample at the
112
+ preview viewport, and its face, weight, line height and letter spacing. A
113
+ face or weight follows the usage until you unlink it, and a size follows its
114
+ recommendation until you type another. A value that leaves its default
115
+ shows a reset icon, each tab's reset button restores its usage, and Reset
116
+ all restores the group. The Body tab ends with the eyebrow, whose sizes
117
+ follow body sm until you edit them.
118
+
119
+ ### Fixed
120
+
121
+ - **Text Styles edits save with the theme and undo like every other edit.**
122
+ The pickers wrote straight to the page's `:root`, so an edit reached neither
123
+ the undo history nor Save. Every Text Styles edit now goes through the
124
+ editor store and lands in the theme's `cssVariables` on Save. A size edit
125
+ writes the step's desktop, tablet or phone size, so the breakpoint
126
+ re-points of its `-font-size` keep working in a promoted theme.
127
+
128
+ ### Migration
129
+
130
+ - Run `npx live-tokens migrate`. The `2026-10-08-type-scales` tokens.css
131
+ migration is breaking, so the dev plugin's `autoMigrate` skips it, and
132
+ check-page reports it as `tokens-breaking-migration` until it runs. It
133
+ renames the three code tokens and every reference to them in `tokens.css`,
134
+ moves a step size you changed into that step's desktop size, keeps a face or
135
+ weight you changed in place of its link, adds the new tokens, and appends
136
+ the re-points to the 768px and 480px blocks. A changed size in rem or px
137
+ sets its step's tablet and phone sizes the way an edit in the editor does.
138
+ A changed size that aliases a primitive, such as `var(--font-size-5xl)`,
139
+ keeps the scale's tablet and phone sizes.
140
+ - Themes need no migration. The editor never saved a text-style edit, so no
141
+ theme holds one.
142
+
3
143
  ## 0.91.2 — Sketch mode claims its parts at ID weight
4
144
 
5
145
  ### Changed
@@ -40,8 +40,8 @@ function capitalize(id) {
40
40
  export const CONTRACT_SCALES = [
41
41
  'surface', 'text', 'border', 'border-width', 'color', 'space', 'radius', 'font', 'line-height',
42
42
  'letter-spacing', 'shadow', 'blur', 'icon-size', 'scrim', 'tint', 'columns',
43
- 'heading', 'body', 'editorial', 'eyebrow', 'code', 'easing', 'duration', 'zoom',
44
- 'gradient', 'stroke',
43
+ 'display', 'heading', 'body', 'editorial', 'eyebrow', 'code', 'type', 'easing', 'duration',
44
+ 'zoom', 'gradient', 'stroke',
45
45
  ];
46
46
 
47
47
  /** True when `name` belongs to a contract-governed scale, so a miss is a typo. */
@@ -99,7 +99,7 @@ export const pageRules = {
99
99
  severity: 'error',
100
100
  repair: 'authored',
101
101
  guidance:
102
- 'The finding names the page file, the line of the text element, and the nearest bundle it missed. Set the text style on the text element itself, from one shipped bundle: heading, body, editorial, or code, each printed by `npx live-tokens tokens --scale <name>`. An ancestor typed for a different role hands down the wrong style.',
102
+ 'The finding names the page file, the line of the text element, and the nearest bundle it missed. Set the text style on the text element itself, from one shipped bundle: display, heading, body, editorial, or code, each printed by `npx live-tokens tokens --scale <name>`. An ancestor typed for a different role hands down the wrong style.',
103
103
  },
104
104
  'page-contrast': {
105
105
  severity: 'error',
@@ -75,7 +75,7 @@ export const pageRules = {
75
75
  severity: 'error',
76
76
  repair: 'choice',
77
77
  guidance:
78
- 'Set every axis from one text style bundle, -font-family through -letter-spacing. The text styles are heading, body, editorial, and code, and `npx live-tokens tokens --scale heading` prints one of them. Rewrite a font: shorthand the same way.',
78
+ 'Set every axis from one text style bundle, -font-family through -letter-spacing. The text styles are display, heading, body, editorial, and code, and `npx live-tokens tokens --scale heading` prints one of them. Rewrite a font: shorthand the same way.',
79
79
  },
80
80
  'hardcoded-columns': {
81
81
  severity: 'warn',
@@ -328,7 +328,7 @@ function checkDeclaration(decl, { text, region, vocab, at }, add) {
328
328
  add(
329
329
  'raw-text-axis',
330
330
  at(index),
331
- `${prop}: ${value}. ${axis} is one axis. Set every axis from one text style bundle (--heading-*, --body-*, --editorial-*, --code-*).`,
331
+ `${prop}: ${value}. ${axis} is one axis. Set every axis from one text style bundle (--display-*, --heading-*, --body-*, --editorial-*, --code-*).`,
332
332
  );
333
333
  return;
334
334
  }
@@ -344,7 +344,7 @@ function checkDeclaration(decl, { text, region, vocab, at }, add) {
344
344
  add(
345
345
  'raw-text-axis',
346
346
  at(index),
347
- `${prop}: ${value}. Set type from a text style bundle (--heading-*, --body-*, --editorial-*, --code-*).`,
347
+ `${prop}: ${value}. Set type from a text style bundle (--display-*, --heading-*, --body-*, --editorial-*, --code-*).`,
348
348
  );
349
349
  return;
350
350
  }