@motion-proto/live-tokens 0.55.1 → 0.57.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.
- package/.claude/skills/{live-tokens-adjust-shape-space → live-tokens-adjust-geometry}/SKILL.md +5 -5
- package/.claude/skills/live-tokens-build-page/SKILL.md +2 -0
- package/.claude/skills/live-tokens-create-component/SKILL.md +20 -357
- package/.claude/skills/live-tokens-create-component/references/fixed-overlays.md +3 -0
- package/.claude/skills/live-tokens-create-component/references/intrinsics.md +58 -0
- package/.claude/skills/live-tokens-create-component/references/linked-siblings.md +70 -0
- package/.claude/skills/live-tokens-generate-theme/SKILL.md +79 -98
- package/.claude/skills/live-tokens-generate-theme/references/named-themes.md +18 -0
- package/.claude/skills/live-tokens-pair-fonts/SKILL.md +88 -0
- package/.claude/skills/live-tokens-pick-component/SKILL.md +4 -1
- package/CHANGELOG.md +197 -0
- package/README.md +21 -8
- package/bin/cli.mjs +42 -3
- package/bin/set-fonts.mjs +280 -0
- package/dist-plugin/adjust/index.cjs +1 -0
- package/dist-plugin/adjust/index.d.cts +3 -3
- package/dist-plugin/adjust/index.d.ts +3 -3
- package/dist-plugin/adjust/index.js +1 -1
- package/dist-plugin/{chunk-TKZBVIW5.js → chunk-E5QYON4L.js} +59 -2
- package/dist-plugin/{chunk-PB2JTK2H.js → chunk-LW4SR7AZ.js} +39 -6
- package/dist-plugin/{chunk-YR6GPXW2.js → chunk-XWXIMTWZ.js} +0 -5
- package/dist-plugin/{chunk-D3ZVKOR4.js → chunk-Y5CNFSSV.js} +1 -0
- package/dist-plugin/{dataPaths-DBN0RPuT.d.cts → dataPaths-CRfD1LdA.d.cts} +3 -0
- package/dist-plugin/{dataPaths-DBN0RPuT.d.ts → dataPaths-CRfD1LdA.d.ts} +3 -0
- package/dist-plugin/fontPairing/index.cjs +413 -0
- package/dist-plugin/fontPairing/index.d.cts +109 -0
- package/dist-plugin/fontPairing/index.d.ts +109 -0
- package/dist-plugin/fontPairing/index.js +321 -0
- package/dist-plugin/generateColorsAndType/index.cjs +22 -9
- package/dist-plugin/generateColorsAndType/index.d.cts +3 -3
- package/dist-plugin/generateColorsAndType/index.d.ts +3 -3
- package/dist-plugin/generateColorsAndType/index.js +8 -5
- package/dist-plugin/index-4N-Orzzi.d.cts +3 -0
- package/dist-plugin/index-4N-Orzzi.d.ts +3 -0
- package/dist-plugin/index.cjs +158 -9
- package/dist-plugin/index.d.cts +1 -1
- package/dist-plugin/index.d.ts +1 -1
- package/dist-plugin/index.js +71 -4
- package/dist-plugin/migrateData/index.cjs +1 -0
- package/dist-plugin/migrateData/index.d.cts +1 -1
- package/dist-plugin/migrateData/index.d.ts +1 -1
- package/dist-plugin/migrateData/index.js +1 -1
- package/dist-plugin/{index-DpTIRZ2H.d.cts → themeTypes-DSV3Zisf.d.cts} +13 -4
- package/dist-plugin/{index-DpTIRZ2H.d.ts → themeTypes-DSV3Zisf.d.ts} +13 -4
- package/dist-plugin/tokensCssMigrations/index.cjs +58 -1
- package/dist-plugin/tokensCssMigrations/index.d.cts +1 -1
- package/dist-plugin/tokensCssMigrations/index.d.ts +1 -1
- package/dist-plugin/tokensCssMigrations/index.js +3 -3
- package/package.json +5 -2
- package/src/editor/core/fonts/applyFontPairing.ts +158 -0
- package/src/editor/core/fonts/fontLoader.ts +1 -0
- package/src/editor/core/fonts/fontMigration.ts +31 -1
- package/src/editor/core/fonts/fontPairing.ts +13 -6
- package/src/editor/core/fonts/googleFontsUrl.ts +123 -0
- package/src/editor/core/fonts/weightCoverage.ts +92 -0
- package/src/editor/core/palettes/paletteDerivation.ts +9 -2
- package/src/editor/core/sketch/maskField.ts +381 -0
- package/src/editor/core/sketch/sketchLayer.ts +1028 -0
- package/src/editor/core/sketch/sketchPresetService.ts +65 -0
- package/src/editor/core/sketch/sketchPresets.ts +328 -0
- package/src/editor/core/sketch/sketchStore.ts +190 -0
- package/src/editor/core/store/editorPersistence.ts +28 -12
- package/src/editor/core/store/editorTypes.ts +4 -1
- package/src/editor/core/store/editorViewStore.ts +2 -2
- package/src/editor/core/store/gradientSource.ts +15 -1
- package/src/editor/core/themes/parsers/gradient.ts +62 -4
- package/src/editor/core/themes/slices/gradients.ts +75 -14
- package/src/editor/core/themes/themeTypes.ts +6 -1
- package/src/editor/docs/Docs.svelte +4 -3
- package/src/editor/docs/chapters.ts +1 -0
- package/src/editor/docs/content/01-overview.md +2 -1
- package/src/editor/docs/content/editing-tokens.md +5 -1
- package/src/editor/docs/content/sketch-mode.md +89 -0
- package/src/editor/docs/content/themes-workflow.md +39 -0
- package/src/editor/docs/content.generated.ts +4 -3
- package/src/editor/overlay/LiveEditorOverlay.svelte +15 -0
- package/src/editor/pages/EditorShell.svelte +43 -0
- package/src/editor/ui/EditorViewSwitcher.svelte +15 -2
- package/src/editor/ui/FontStackEditor.svelte +3 -0
- package/src/editor/ui/GradientEditor.svelte +38 -1
- package/src/editor/ui/ProjectFontsSection.svelte +24 -36
- package/src/editor/ui/UIReveal.svelte +7 -1
- package/src/editor/ui/UISegmentedControl.svelte +4 -8
- package/src/editor/ui/sections/GradientsSection.svelte +47 -1
- package/src/editor/ui/sketch/SketchDial.svelte +124 -0
- package/src/editor/ui/sketch/SketchPreview.svelte +119 -0
- package/src/editor/ui/sketch/SketchRange.svelte +185 -0
- package/src/editor/ui/sketch/SketchTab.svelte +1263 -0
- package/src/live-tokens/data/colors-and-type/autumn.json +17 -0
- package/src/live-tokens/data/colors-and-type/default.json +17 -0
- package/src/live-tokens/data/colors-and-type/halloween.json +17 -0
- package/src/live-tokens/data/colors-and-type/midnight-study.json +17 -0
- package/src/live-tokens/data/colors-and-type/ocean.json +17 -0
- package/src/live-tokens/data/colors-and-type/royal-velvet.json +17 -0
- package/src/live-tokens/data/colors-and-type/sketches.json +2520 -0
- package/src/live-tokens/data/colors-and-type/spring-meadow.json +17 -0
- package/src/live-tokens/data/colors-and-type/sunset.json +17 -0
- package/src/live-tokens/data/themes/autumn.json +17 -0
- package/src/live-tokens/data/themes/halloween.json +17 -0
- package/src/live-tokens/data/themes/midnight-study.json +17 -0
- package/src/live-tokens/data/themes/ocean.json +17 -0
- package/src/live-tokens/data/themes/royal-velvet.json +17 -0
- package/src/live-tokens/data/themes/sketches.json +3984 -0
- package/src/live-tokens/data/themes/spring-meadow.json +17 -0
- package/src/live-tokens/data/themes/sunset.json +17 -0
- package/src/live-tokens/data/tokens.generated.css +1 -0
- package/src/system/styles/tokens.css +15 -2
|
@@ -1,22 +1,24 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: live-tokens-generate-theme
|
|
3
|
-
description: Generate a complete live-tokens color
|
|
3
|
+
description: Generate a complete live-tokens theme (color, type, and geometry) from a natural-language mood brief. Chooses 10 OKLCH seeds and runs the packaged generator, which enforces AA contrast, then carries the same brief into a font pairing and a geometry through the sibling skills. Use whenever the user asks for a theme, a look, a vibe, a brand feel, a color scheme, or a palette, by mood, season, holiday, or hue, even if they only mention color: make me a bright and cheerful theme, a dark moody night theme, a St. Patrick's Day theme in green and gold, a Christmas look, something red-based, warmer, more contrast, calmer. Not for a single token (use the editor), for type alone (live-tokens-pair-fonts), or for geometry alone (live-tokens-adjust-geometry).
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Generating a theme from a mood brief
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
A theme is three decisions made from one brief: color, type, and geometry. This skill owns the color decision directly and delegates the other two, so the whole look comes from the same reading of the brief. Never hand-author theme JSON and never edit the data tree directly.
|
|
9
9
|
|
|
10
10
|
## Workflow
|
|
11
11
|
|
|
12
|
-
1.
|
|
13
|
-
2.
|
|
14
|
-
3.
|
|
15
|
-
4.
|
|
12
|
+
1. Read the brief once and name its voice in a sentence: the mood, the hue family, the scheme, and the type and geometry that mood implies. Everything below keys off that sentence.
|
|
13
|
+
2. Translate the brief into a seed file using the framework below. Write it to `scratch/theme-brief.json`.
|
|
14
|
+
3. Run `npx live-tokens generate-theme scratch/theme-brief.json`. It writes `themes/<slug>.json`, opens that theme, and prints a contrast report. Auto-corrections are fine. Unmet floors (exit 1) mean the seeds themselves are unworkable; each failure line names the seed to change, usually by raising its lightness or cutting its chroma. Fix the brief and re-run; the same name overwrites. Regeneration replaces that theme's whole color state, including palette edits made in the editor since the last run, so say so once when iterating.
|
|
15
|
+
4. Invoke **live-tokens-pair-fonts** with the same voice. Skip only when the user asked for colors specifically and said to leave the type alone.
|
|
16
|
+
5. Invoke **live-tokens-adjust-geometry** with the geometry the voice implies (table below). Skip when the voice implies nothing about geometry.
|
|
17
|
+
6. Tell the user to look at the running app, and that type and geometry sit in the unsaved buffer until they save the open theme. Offer refinements as edits to the same brief.
|
|
16
18
|
|
|
17
|
-
|
|
19
|
+
Order matters only for safety, and the order above is safe: the color generator carries the live buffers forward into the new theme file, so a color re-roll after fonts and geometry keeps both.
|
|
18
20
|
|
|
19
|
-
|
|
21
|
+
Flags: `--dry-run` prints the report without writing; `--no-activate` writes without opening. Opening a theme never changes what the site ships. Only Adopt, in the editor, does that.
|
|
20
22
|
|
|
21
23
|
## The brief
|
|
22
24
|
|
|
@@ -28,140 +30,119 @@ Warn once per session when iterating: regeneration replaces the whole color stat
|
|
|
28
30
|
"Brand": { "l": 0.62, "c": 0.17, "h": 145 },
|
|
29
31
|
"Accent": { "l": 0.80, "c": 0.15, "h": 95 },
|
|
30
32
|
"Special": { "l": 0.60, "c": 0.19, "h": 300 },
|
|
31
|
-
"Canvas": { "l": 0.
|
|
33
|
+
"Canvas": { "l": 0.93, "c": 0.04, "h": 120 },
|
|
32
34
|
"Neutral": { "l": 0.55, "c": 0.012, "h": 140 },
|
|
33
35
|
"Alternate": { "l": 0.58, "c": 0.009, "h": 60 },
|
|
34
36
|
"Info": { "l": 0.60, "c": 0.15, "h": 255 },
|
|
35
37
|
"Success": { "l": 0.60, "c": 0.16, "h": 150 },
|
|
36
38
|
"Warning": { "l": 0.75, "c": 0.15, "h": 85 },
|
|
37
39
|
"Danger": { "l": 0.58, "c": 0.20, "h": 25 }
|
|
38
|
-
}
|
|
39
|
-
"harmony": { "mode": "analogous" }
|
|
40
|
+
}
|
|
40
41
|
}
|
|
41
42
|
```
|
|
42
43
|
|
|
43
|
-
All 10 seeds are required
|
|
44
|
+
All 10 seeds are required; a seed may also be a `"#rrggbb"` string. OKLCH: `l` is 0 to 1 lightness, `c` is chroma (0 grey, about 0.37 max), `h` is hue in degrees. `name` becomes the file slug; `"default"` is refused. `canvasGradient` is an optional boolean, see below.
|
|
44
45
|
|
|
45
|
-
Roles: **Brand** is the dominant chromatic identity; **Accent** the supporting color; **Special** the rare expressive tertiary; **Canvas** is the page background verbatim; **Neutral** drives
|
|
46
|
+
Roles: **Brand** is the dominant chromatic identity; **Accent** the supporting color; **Special** the rare expressive tertiary; **Canvas** is the page background verbatim; **Neutral** drives neutral surfaces and body text; **Alternate** is the second near-grey family; the four statuses are conventional signals.
|
|
46
47
|
|
|
47
48
|
## Chroma budget: color is inversely proportional to area
|
|
48
49
|
|
|
49
50
|
| Tier | Palettes | Chroma |
|
|
50
51
|
|---|---|---|
|
|
51
|
-
| Ground (
|
|
52
|
-
| Dominant chromatic (
|
|
53
|
-
| Garnish (
|
|
54
|
-
| Conditional | Info, Success, Warning, Danger | C 0.12
|
|
52
|
+
| Ground (about 60% of every screen) | Canvas, Neutral, Alternate | C 0.005 to 0.03 |
|
|
53
|
+
| Dominant chromatic (about 30%) | Brand | C 0.10 to 0.20 |
|
|
54
|
+
| Garnish (about 10%) | Accent, Special | may exceed Brand; at most one at full saturation |
|
|
55
|
+
| Conditional | Info, Success, Warning, Danger | C 0.12 to 0.19 |
|
|
55
56
|
|
|
56
|
-
A good theme reads as 3
|
|
57
|
+
A good theme reads as 3 or 4 hue families on screen, never 10. Neutral and Alternate stay near-grey but tinted toward the theme (Neutral near Brand's hue; Alternate offset 15 to 60 degrees, or a warm/cool counterpoint), never pure C = 0.
|
|
57
58
|
|
|
58
59
|
## Per-role bands
|
|
59
60
|
|
|
60
61
|
| Seed | Light scheme | Dark scheme | Hue |
|
|
61
62
|
|---|---|---|---|
|
|
62
|
-
| Canvas | L 0.92
|
|
63
|
-
| Neutral
|
|
64
|
-
| Brand | L 0.45
|
|
65
|
-
| Accent | harmony slot, or
|
|
66
|
-
| Special | most expressive; default
|
|
67
|
-
| Info | shared status L (0.55
|
|
68
|
-
| Success | shared status L | same | H 140
|
|
69
|
-
| Warning | L
|
|
70
|
-
| Danger | shared status L, C 0.15
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
-
|
|
63
|
+
| Canvas | L 0.92 to 0.98, C 0.02 to 0.06 | L 0.15 to 0.28, C 0.01 to 0.05 | Brand's hue or its harmony slot |
|
|
64
|
+
| Neutral, Alternate | L about 0.55, C 0.008 to 0.02 | same | per the chroma budget |
|
|
65
|
+
| Brand | L 0.45 to 0.62, C 0.12 to 0.20 | L 0.70 to 0.83, C cut by a third | the brief's identity hue |
|
|
66
|
+
| Accent | harmony slot, or at least 0.25 L from Brand when the mode collapses hue distance | lighten and desaturate like Brand | harmony slot |
|
|
67
|
+
| Special | most expressive; default Brand hue +60 at about 65% of Brand's C | same transform | harmony slot |
|
|
68
|
+
| Info | shared status L (0.55 to 0.65 light) | lighten like Brand | H 230 to 260 |
|
|
69
|
+
| Success | shared status L | same | H 140 to 155 |
|
|
70
|
+
| Warning | L 0.75 or higher (vivid yellow must be light) | same | H 70 to 90 |
|
|
71
|
+
| Danger | shared status L, C 0.15 to 0.20 | same | H 20 to 30 |
|
|
72
|
+
|
|
73
|
+
**The canvas carries the theme's identity, so commit to it.** The page background is the largest area on screen and the strongest difference between themes; a timid canvas makes every theme look the same. Below C 0.015 at L 0.95 a tint is imperceptible, which makes near-white a deliberate choice for clean or minimal briefs and never the default. Three levels of commitment:
|
|
74
|
+
|
|
75
|
+
1. *Tinted paper* (most UI briefs): C 0.02 to 0.06, with L down to 0.92 where the hue needs room.
|
|
76
|
+
2. *Colored ground* (expressive briefs): L 0.85 to 0.92 at C 0.05 to 0.10. The page is unmistakably mint, parchment, sky.
|
|
77
|
+
3. *Full-color ground* (holiday and statement briefs): the canvas is the theme color, like a red Christmas page with green and gold on it. Keep canvas L at or below 0.48 or at or above 0.85 so text has somewhere to go; the contrast gate enforces legibility either way.
|
|
78
|
+
|
|
79
|
+
Also:
|
|
80
|
+
|
|
81
|
+
- Blue tints cap very low at high L (H 264 at L 0.95 barely reaches C 0.03): lower L for a blue canvas rather than fighting the ceiling. Yellow, green, and cream tint generously at high L.
|
|
82
|
+
- When generating a set of themes, make the canvases pairwise distinct in hue or in L. Two light themes both near (0.97, 0.01) read as one theme with different buttons.
|
|
83
|
+
- A dark scheme is a transform, not just a dark canvas: every chromatic seed lightens to L 0.75 to 0.85 and drops about a third of its chroma, because saturated color vibrates on dark grounds.
|
|
84
|
+
- Equal lightness reads as equal weight: give the four statuses one shared L, and do the same for Brand and Accent when they should balance.
|
|
85
|
+
- Status hues never rotate with the harmony; only their L and C adapt to the mood.
|
|
81
86
|
|
|
82
87
|
## Mood dials
|
|
83
88
|
|
|
84
|
-
|
|
89
|
+
Pleasantness rises with lightness (strongly) and saturation (weakly); energy rises with saturation; drama rises with dark plus saturated.
|
|
85
90
|
|
|
86
91
|
| Brief says | Dials |
|
|
87
92
|
|---|---|
|
|
88
|
-
| cheerful, bright, playful | light
|
|
89
|
-
| calm, serene, soft | light
|
|
90
|
-
| energetic, bold | C
|
|
91
|
-
| dark, moody, dramatic, luxurious | dark
|
|
92
|
-
| professional, trustworthy | blue 230
|
|
93
|
-
| warm / cool | hues 20
|
|
93
|
+
| cheerful, bright, playful | light; Brand and Accent L 0.7 to 0.9, C 0.15 to 0.22; warm hues 40 to 140 (yellow is the strongest joy hue) |
|
|
94
|
+
| calm, serene, soft | light; C 0.03 to 0.08 on everything chromatic; cool hues 140 to 260 |
|
|
95
|
+
| energetic, bold | C 0.18 or more at L 0.55 to 0.65; red, orange, magenta |
|
|
96
|
+
| dark, moody, dramatic, luxurious | dark; Canvas L 0.15 to 0.25; purple, deep blue, crimson; working accents stay light per the dark transform, with dark saturated color saved for one or two moments |
|
|
97
|
+
| professional, trustworthy | blue 230 to 265, C 0.08 to 0.15; everything else muted |
|
|
98
|
+
| warm / cool | hues 20 to 110 plus pink 290 to 360 / hues 140 to 290 |
|
|
94
99
|
|
|
95
|
-
Avoid mid-lightness yellow-green (H 100
|
|
100
|
+
Avoid mid-lightness yellow-green (H 100 to 120 at L 0.5 to 0.7, C about 0.1) unless the brief asks for olive or toxic.
|
|
96
101
|
|
|
97
|
-
## Gamut guardrails
|
|
102
|
+
## Gamut guardrails
|
|
98
103
|
|
|
99
|
-
|
|
100
|
-
- Vivid light blue does not exist: H 264 at L 0.9 caps at C ≈ 0.05. Rich blue lives at L 0.40–0.55.
|
|
101
|
-
- Teal/sky cap at C ≈ 0.15; a "vivid teal" is C 0.13–0.15.
|
|
102
|
-
- Peak chroma anchors: red H20 C 0.25 @ L 0.63; orange H60 C 0.18 @ L 0.76; yellow H90 C 0.18 @ L 0.86; green H140 C 0.28 @ L 0.88; blue H264 C 0.28 @ L 0.50; magenta H320 C 0.31 @ L 0.65.
|
|
104
|
+
The engine clamps to gamut regardless; these keep your intent achievable rather than silently muted.
|
|
103
105
|
|
|
104
|
-
|
|
106
|
+
- Dark saturated yellow does not exist: H 90 at L 0.4 caps at C 0.08 and reads olive. Vivid yellow needs L 0.8 or more. Brown is dark low-chroma orange.
|
|
107
|
+
- Vivid light blue does not exist: H 264 at L 0.9 caps at C 0.05. Rich blue lives at L 0.40 to 0.55.
|
|
108
|
+
- Teal and sky cap at C 0.15.
|
|
109
|
+
- Peak chroma anchors: red H20 C 0.25 at L 0.63; orange H60 C 0.18 at L 0.76; yellow H90 C 0.18 at L 0.86; green H140 C 0.28 at L 0.88; blue H264 C 0.28 at L 0.50; magenta H320 C 0.31 at L 0.65.
|
|
105
110
|
|
|
106
|
-
##
|
|
111
|
+
## Harmony
|
|
107
112
|
|
|
108
|
-
|
|
113
|
+
Hue offsets from Brand: complementary +180; split-complementary +150/+210; triadic +120/+240; tetradic +60/+180/+240; square +90 steps; compound +30/+180/+210; analogous plus or minus 30; monochromatic same hue.
|
|
109
114
|
|
|
110
|
-
-
|
|
111
|
-
-
|
|
112
|
-
- Drama or maximum contrast
|
|
115
|
+
- A vague or single-adjective brief takes monochromatic or analogous, with Accent separated from Brand by L and C rather than hue. The polished-UI default: Accent at Brand's hue and about 45% of its chroma, Special at +60 and about 65%.
|
|
116
|
+
- A brief naming two colors: measure their hue gap and pick the matching mode (green plus gold is 60 to 90 degrees, so analogous or compound).
|
|
117
|
+
- Drama or maximum contrast: complementary, triadic, or tetradic, and then tone one side down, since max-chroma text on a near-black ground vibrates.
|
|
113
118
|
|
|
114
|
-
##
|
|
119
|
+
## Canvas sky and shadows
|
|
115
120
|
|
|
116
|
-
|
|
117
|
-
vertical gradient built from the Canvas ramp. The engine picks the stops itself
|
|
118
|
-
(two ramp steps from the Canvas anchor on the scheme's safe side), so the
|
|
119
|
-
choice you make is only *whether*, never *how*.
|
|
121
|
+
`"canvasGradient": true` renders the page background as a vertical gradient from the Canvas ramp. Default off. Turn it on only when the brief evokes atmosphere (sky, night, dusk, glow, underwater) or asks for a gradient outright; keep it off for crisp, flat, minimal, or corporate briefs and whenever in doubt, because a sky on every theme stops meaning anything. It needs a committed canvas (level 2 or 3); at the ramp edge the engine skips it and says so. Say why you enabled it in one line.
|
|
120
122
|
|
|
121
|
-
|
|
122
|
-
dusk, dawn, sunset, glow, candlelight, underwater, depth — or when the user
|
|
123
|
-
asks for a gradient outright. Keep it off for crisp, clean, flat, minimal, or
|
|
124
|
-
corporate briefs, and whenever in doubt. Most themes should not have one; a sky
|
|
125
|
-
that appears on every generated theme stops meaning anything. When you enable
|
|
126
|
-
it, say why in one sentence when reporting back ("night brief → canvas sky").
|
|
123
|
+
Shadow opacity derives from Canvas lightness and re-derives on every run, so there is nothing to choose. When shadows read heavy or muddy, raise the Canvas seed's L.
|
|
127
124
|
|
|
128
|
-
|
|
129
|
-
(near-white light canvas, near-black dark one) there is no room on the safe
|
|
130
|
-
side and the engine skips the sky, saying so in the report. An atmospheric
|
|
131
|
-
brief that wants one should already be at canvas commitment level 2–3.
|
|
125
|
+
## Named themes
|
|
132
126
|
|
|
133
|
-
|
|
127
|
+
A holiday or season brief is a statement brief: commitment level 2 or 3, with the named color on the ground rather than only on the buttons. Read `references/named-themes.md` for the OKLCH anchors of Christmas, Halloween, St. Patrick's, Ocean, Sunset, Autumn, and Spring before seeding one.
|
|
134
128
|
|
|
135
|
-
|
|
136
|
-
lightness and carries each shadow's geometry and color through untouched. A
|
|
137
|
-
near-black shadow at 0.9 opacity is what a dark ground needs to show any
|
|
138
|
-
shadow at all, and it punches a hole in paper, so opacity holds at 0.9 up to
|
|
139
|
-
canvas L 0.5 and eases to 0.2 by L 0.9. There is nothing to choose: the report
|
|
140
|
-
prints the derived value, and every regeneration re-derives it, so a brief
|
|
141
|
-
iterated from a light canvas to a dark one gets its weight back.
|
|
129
|
+
## Geometry from the voice
|
|
142
130
|
|
|
143
|
-
|
|
144
|
-
lever. Raise the Canvas seed's lightness and the shadows lighten with it. A
|
|
145
|
-
one-off override lives in the editor's Shadows tab and survives regeneration
|
|
146
|
-
in everything except opacity.
|
|
131
|
+
The geometry lives in radius, padding, gap, and border width, and `live-tokens-adjust-geometry` knows the mechanics. Hand it the intent:
|
|
147
132
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
- **St. Patrick's**: green (0.51, 0.13, 152) Brand, gold Accent, white/beige neutrals.
|
|
155
|
-
- **Ocean**: deep blue (0.35, 0.08, 237) vs aqua (0.78, 0.12, 214); H 180–240.
|
|
156
|
-
- **Sunset**: hues 90 → 320 through red, L falling 0.85 → 0.40.
|
|
157
|
-
- **Autumn / Fall**: leaves and dry grass — canvas warm tan/parchment (0.87, 0.06, 80), rust Brand (0.55, 0.15, 40), golden Accent (0.75, 0.15, 85), moss/olive Special (0.55, 0.10, 120), warm brown neutrals H 50–70. Deep red H 25 welcome. **Spring**: pastels L 0.85–0.95, C 0.04–0.10, greens 130–150 / pinks 0–20, mint canvas.
|
|
133
|
+
| Voice | Geometry |
|
|
134
|
+
|---|---|
|
|
135
|
+
| playful, friendly, soft | rounder, a step airier; pill buttons when the brief is warm |
|
|
136
|
+
| luxurious, elegant, editorial | sharper corners, airier padding, thin borders |
|
|
137
|
+
| technical, dense, systematic | tighter spacing, small radius, square corners on containers |
|
|
138
|
+
| calm, minimal | leave geometry alone unless the brief says otherwise |
|
|
158
139
|
|
|
159
|
-
##
|
|
140
|
+
## What each step writes
|
|
160
141
|
|
|
161
|
-
|
|
142
|
+
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.
|
|
162
143
|
|
|
163
144
|
## Verify
|
|
164
145
|
|
|
165
|
-
- The CLI exits 0
|
|
166
|
-
- The app (dev server running) shows the
|
|
167
|
-
-
|
|
146
|
+
- The color CLI exits 0 with every check passing (auto-corrected is fine), and the two sibling skills report what they changed.
|
|
147
|
+
- The app (dev server running) shows the whole look after a reload, and the editor's Theme panel names the theme.
|
|
148
|
+
- To return to the previous look, load the theme the CLI output named from the Theme panel; that discards the buffers too.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Named themes: canonical OKLCH anchors
|
|
2
|
+
|
|
3
|
+
Read this when the brief names a holiday, a season, or a natural scene. These
|
|
4
|
+
are starting points, not seeds to copy: apply the chroma budget, per-role bands,
|
|
5
|
+
and canvas commitment rules from SKILL.md on top of them.
|
|
6
|
+
|
|
7
|
+
Holiday briefs are statement briefs. Default to canvas commitment level 2 or 3,
|
|
8
|
+
never cream, and put the named color on the ground, not only on the buttons.
|
|
9
|
+
|
|
10
|
+
| Brief | Anchors (L, C, H) | Strongest form |
|
|
11
|
+
|---|---|---|
|
|
12
|
+
| Christmas | red (0.53, 0.21, 22), green (0.46, 0.11, 155), gold (0.77, 0.14, 91) | red canvas (0.42, 0.14, 25), green Brand, gold Accent, dark scheme. Softer: evergreen canvas (0.35, 0.07, 160) or deep cream (0.95, 0.04, 85). One of red or green owns the ground; never a 50/50 split. |
|
|
13
|
+
| Halloween | pumpkin (0.70, 0.20, 46), purple (0.51, 0.21, 313), poison green (0.73, 0.20, 137) | orange canvas (0.45, 0.13, 55) with violet and poison-green accents, or near-black violet canvas with pumpkin Brand. Dark scheme either way. |
|
|
14
|
+
| St. Patrick's | green (0.51, 0.13, 152) | green Brand, gold Accent, white or beige neutrals. |
|
|
15
|
+
| Ocean | deep blue (0.35, 0.08, 237), aqua (0.78, 0.12, 214) | hues held to 180 to 240. |
|
|
16
|
+
| Sunset | hues 90 to 320 through red | L falls 0.85 to 0.40 across the sweep. |
|
|
17
|
+
| Autumn | parchment canvas (0.87, 0.06, 80), rust Brand (0.55, 0.15, 40), gold Accent (0.75, 0.15, 85), moss Special (0.55, 0.10, 120) | warm brown neutrals H 50 to 70; deep red H 25 welcome. |
|
|
18
|
+
| Spring | pastels L 0.85 to 0.95, C 0.04 to 0.10 | greens 130 to 150, pinks 0 to 20, mint canvas. |
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: live-tokens-pair-fonts
|
|
3
|
+
description: Choose and apply a Google Fonts pairing for a live-tokens theme by binding families to the --font-display, --font-sans, --font-serif, --font-mono and --font-editorial stacks. Use whenever the user asks to pair fonts, pick a typeface, change or set the fonts, or describes type by voice: give me a font pairing, what font should the headings use, make the type more editorial, friendlier, more technical, more elegant, a serif for headings, a display font for this theme, less generic type, match the fonts to the theme. Also invoked by live-tokens-generate-theme for the type half of a whole look. Changes type only, never color. Not for a single token (use the editor) or for color (see live-tokens-generate-theme).
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Pairing fonts for a theme
|
|
7
|
+
|
|
8
|
+
You choose the families; the CLI verifies each against Google Fonts, builds the URL from the weights the family actually has, and writes the result into the unsaved buffer. Never hand-author font JSON and never edit the data tree directly. Google Fonts is the pool because it is freely licensable and loads by URL; other sources go in by hand through the editor's Project fonts section.
|
|
9
|
+
|
|
10
|
+
## Workflow
|
|
11
|
+
|
|
12
|
+
1. Choose the pairing with the framework below and write a brief to `scratch/font-brief.json`.
|
|
13
|
+
2. Run `npx live-tokens set-fonts scratch/font-brief.json`. It prints each stack that moved, each family's real weights and URL, and the weights your typography tokens ask for that the family lacks.
|
|
14
|
+
3. Read the report. A weight gap is a quality note: name it and offer an alternative only if it matters (a body face without 400 or 700 matters; a display face without 300 does not). A family not on Google Fonts fails the run; fix the spelling and re-run.
|
|
15
|
+
4. Tell the user to reload and look, and that the edit is unsaved until they save the open theme.
|
|
16
|
+
|
|
17
|
+
State your reasoning when you propose the pairing: each face's form model and the matrix verdict, in one sentence, so the user can argue with the argument rather than only the result.
|
|
18
|
+
|
|
19
|
+
Flags: `--dry-run` reports without writing. `--no-verify` skips the network and requires an explicit URL per family; use it only offline with a URL in hand.
|
|
20
|
+
|
|
21
|
+
## The brief
|
|
22
|
+
|
|
23
|
+
```json
|
|
24
|
+
{ "display": "Fraunces", "body": "Nunito Sans" }
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Every slot is optional and an omitted slot is left exactly as it is. `display` is `--font-display`, `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 style: it tracks the body face until a theme repoints it, so set it only when essays and articles should not carry the body face. A slot may be `{ "name": "...", "url": "..." }` to pin an exact URL. Spell families as Google does; the CLI reports the canonical spelling back.
|
|
28
|
+
|
|
29
|
+
## Choose the body face first
|
|
30
|
+
|
|
31
|
+
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 brief, then pick the display face against it. A body face must have regular, bold, and italic; low to moderate stroke contrast; open apertures; and a large x-height. A face failing any of these is a display face whatever its name says. Single-weight families are fine for `display` and disqualifying for `body`.
|
|
32
|
+
|
|
33
|
+
## The font matrix: the decision rule
|
|
34
|
+
|
|
35
|
+
Classify each candidate on two layers. The **skeleton** is its form model; the **flesh** is its stroke contrast and serif treatment.
|
|
36
|
+
|
|
37
|
+
| Form model | Construction | Reads as |
|
|
38
|
+
|---|---|---|
|
|
39
|
+
| **Dynamic** | diagonal stress, open apertures, written origin | open, warm, humane, timeless |
|
|
40
|
+
| **Rational** | vertical stress, closed apertures, drawn not written | orderly, reserved, elegant, authoritative |
|
|
41
|
+
| **Geometric** | monolinear, circle-and-line | technical, modern, systematic, sober |
|
|
42
|
+
|
|
43
|
+
- **Same skeleton, different flesh: reliable.** Helvetica and Bodoni are both rational, one a linear sans and one a contrasting serif.
|
|
44
|
+
- **Same flesh, different skeleton: the failure case.** The two look alike on the surface and fight underneath. This is why two arbitrary sans-serifs so often clash.
|
|
45
|
+
- **Far apart on both: works, deliberately.** An unmistakable difference reads as a decision.
|
|
46
|
+
|
|
47
|
+
Many faces sit between columns. When one straddles, say so and lean on the voice table and the x-height check instead.
|
|
48
|
+
|
|
49
|
+
## Voice
|
|
50
|
+
|
|
51
|
+
| Brief says | Type voice |
|
|
52
|
+
|---|---|
|
|
53
|
+
| editorial, literary, considered | dynamic serif display over a humanist sans body |
|
|
54
|
+
| elegant, luxurious, formal | rational high-contrast serif display; keep the body quiet |
|
|
55
|
+
| friendly, warm, approachable | dynamic sans on both sides, or a soft serif display |
|
|
56
|
+
| technical, systematic, precise | geometric or neo-grotesque sans; a mono for code |
|
|
57
|
+
| playful, informal | an expressive display face over a plain workhorse body |
|
|
58
|
+
| serious, institutional, trustworthy | rational sans body, rational serif display |
|
|
59
|
+
| quiet, minimal, unbranded | one superfamily across both slots |
|
|
60
|
+
|
|
61
|
+
Match the type to the same brief the color came from. A warm autumn palette under a cold geometric sans reads as two projects.
|
|
62
|
+
|
|
63
|
+
## Shortcuts
|
|
64
|
+
|
|
65
|
+
These find an adequate pairing fast and skip the reasoning; use them when the brief is vague or the type should stay quiet.
|
|
66
|
+
|
|
67
|
+
- **A superfamily.** Google Fonts families with both sans and serif siblings: Alegreya, Ancizar, IBM Plex, Inria, Merriweather, Noto, PT, Roboto, Source.
|
|
68
|
+
- **One family across weights.**
|
|
69
|
+
- **Same designer or foundry.**
|
|
70
|
+
- **Serif display over sans body** when nothing else decides it.
|
|
71
|
+
|
|
72
|
+
## Watch for
|
|
73
|
+
|
|
74
|
+
- **x-height parity.** Both faces are set from one size scale, so a small-x-height display face over a large-x-height body face gives a heading that looks weaker than its own body text. This is the one visual check that matters on screen; make it on the rendered page.
|
|
75
|
+
- **Print faces at small sizes.** Delicate serifs and high stroke contrast turn to mud below 16px.
|
|
76
|
+
- **Every family is a request.** Two is the target; three needs a reason.
|
|
77
|
+
- **Sets of themes:** no two share a display face or a body face.
|
|
78
|
+
|
|
79
|
+
## Scope
|
|
80
|
+
|
|
81
|
+
Type only. Color, component aliases, shape, and the type scale are untouched: `set-fonts` moves families between stacks and nothing else, writing only the unsaved colors-and-type buffer. Save the theme to keep it, Adopt to ship it.
|
|
82
|
+
|
|
83
|
+
## Verify
|
|
84
|
+
|
|
85
|
+
- The CLI exits 0 and names each stack that moved, before and after.
|
|
86
|
+
- Each URL reflects the family's real weights: a range for a variable family, an enumeration for a static one, a bare URL for a single-weight face.
|
|
87
|
+
- The app shows the new type after a reload, and the editor's Fonts section lists both families with their fallbacks intact.
|
|
88
|
+
- To revert, run the inverse brief, or load the open theme again to discard the buffer.
|
|
@@ -11,7 +11,7 @@ For composing a page once you've picked components, see [[live-tokens-build-page
|
|
|
11
11
|
|
|
12
12
|
## Catalogue
|
|
13
13
|
|
|
14
|
-
Action: `Button`, `IconButton`. Input: `Input`. Selection: `SegmentedControl`, `TabBar`, `RadioButton`, `MenuSelect`, `Toggle`. Containers: `Card`, `CollapsibleSection`, `Dialog`. Messaging: `Callout`, `Notification`, `Tooltip`, `Badge`, `CornerBadge`. Display: `Table`, `Image`, `ImageLightbox`, `ProgressBar`, `SectionDivider`, `SideNavigation`, `CodeSnippet`.
|
|
14
|
+
Action: `Button`, `IconButton`, `InlineEditActions`. Input: `Input`. Selection: `SegmentedControl`, `TabBar`, `RadioButton`, `MenuSelect`, `Toggle`. Containers: `Card`, `CollapsibleSection`, `Dialog`, `Panel`. Messaging: `Callout`, `Notification`, `Tooltip`, `Badge`, `CornerBadge`. Display: `Table`, `Image`, `ImageLightbox`, `ProgressBar`, `SectionDivider`, `SideNavigation`, `CodeSnippet`.
|
|
15
15
|
|
|
16
16
|
`CodeSnippet` is for a single-line command or value the user is meant to copy and paste back into a terminal (install commands, generated keys, ids). Click-to-copy with a brief "Copied" popover. Use it whenever your page asks the reader to *run* something, rather than just *read* it.
|
|
17
17
|
|
|
@@ -22,6 +22,7 @@ Both trigger an action and share the same six variants (primary, secondary, outl
|
|
|
22
22
|
- `Button` carries a text label, optionally with a leading or trailing icon. Use it whenever the action needs a word to be unambiguous.
|
|
23
23
|
- `IconButton` is icon-only and square. Use it for compact, space-constrained actions whose meaning is obvious from the glyph alone (toolbar controls, close/edit/delete affordances, card overflow menus). It has no text slot, so an `ariaLabel` is required for accessibility.
|
|
24
24
|
- **Don't reach for `IconButton` when the icon's meaning isn't self-evident.** A labelled `Button` (or a `Button` with an icon) avoids the guessing game.
|
|
25
|
+
- `InlineEditActions` is the confirm-and-cancel pair that follows an inline edit (rename a row, edit a value in place). Use it rather than two loose `IconButton`s so every inline edit on the page resolves the same way.
|
|
25
26
|
|
|
26
27
|
## Single-selection family: SegmentedControl vs TabBar vs RadioButton vs MenuSelect
|
|
27
28
|
|
|
@@ -46,9 +47,11 @@ All four pick one option from a set. The right one depends on **option count**,
|
|
|
46
47
|
| `Card` | Inline, always open | Default container for grouped content |
|
|
47
48
|
| `CollapsibleSection` | Inline, toggleable | Progressive disclosure inside a longer page |
|
|
48
49
|
| `Dialog` | Modal, blocks page | Confirmations, focused tasks the page can't continue around |
|
|
50
|
+
| `Panel` | Inline, fixed stage | A demo or preview surface whose height must not reflow |
|
|
49
51
|
|
|
50
52
|
- Default to `Card`. It's the workhorse.
|
|
51
53
|
- 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.
|
|
54
|
+
- `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`.
|
|
52
55
|
- **Don't use `Dialog` for routine forms.** Reach for it only when the page cannot meaningfully continue until the user decides (destructive confirmations, payment, sign-in). Routine forms go inline in a `Card`.
|
|
53
56
|
|
|
54
57
|
## Messaging family: Callout vs Notification vs Tooltip vs Badge
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,202 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.57.0 — A theme can be drawn by hand
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- **Sketch mode: a fourth editor view, beside Tokens, Colors and Components.**
|
|
8
|
+
It is an effect layer over the active theme, not a set of theme values. It
|
|
9
|
+
reads nothing from the theme and writes nothing back. Each component's fill
|
|
10
|
+
and outline are repainted onto `::before`/`::after` from the tokens that
|
|
11
|
+
component already owns (`--<component>-<variant>-surface`, `-border`,
|
|
12
|
+
`-radius`), the real background and border are hidden behind them, and both
|
|
13
|
+
are pushed around one shared noise field. Turning it off removes every trace.
|
|
14
|
+
While it is on it applies to the page behind the editor as well as to the
|
|
15
|
+
preview, because the layer is injected into every document `cssVarSync`
|
|
16
|
+
tracks. Scope is the `data-sketch` attribute, so it switches on for a whole
|
|
17
|
+
document root or for one preview container.
|
|
18
|
+
- **Seven shipped looks, and every dial behind them.** Pencil, Marker,
|
|
19
|
+
Whiteboard, Hatched, Dashed, Napkin and Dry marker, each a complete set of
|
|
20
|
+
settings with a blurb naming what it is. The dials sit under five headings:
|
|
21
|
+
**Border** (travel, wavelength, width, ink, pressure, pooling, dashes, a
|
|
22
|
+
second pass that either copies the first line or runs it through the pen again
|
|
23
|
+
on its own seed), **Fill** (solid or hatched, travel, per-instance offset,
|
|
24
|
+
rotation and scale), **Shape** (corner spread, and a corner travel that leans
|
|
25
|
+
the drawn box into a quadrilateral with no two sides parallel), **Icons and
|
|
26
|
+
SVG** (glyph travel and wavelength on their own scale, because a glyph is all
|
|
27
|
+
curves and needs more travel than a card's long straight edge), and **Noise**
|
|
28
|
+
(the shared displacement field's wavelength, roughness and waveform).
|
|
29
|
+
- **Ink coverage as a generated field.** The mask that thins a fill is a tiling
|
|
30
|
+
Perlin field rasterised to a greyscale PNG and applied with `mask-mode:
|
|
31
|
+
luminance`, rather than an `feTurbulence` primitive. Turbulence lands in a
|
|
32
|
+
narrow band around its own midpoint, so a dial walking a cut across 0 to 1
|
|
33
|
+
spends most of its travel outside the field and the rest reads as flat grey.
|
|
34
|
+
Generated, the tile is stretched onto its own measured range first, so Min and
|
|
35
|
+
Max always mean levels at every grain and octave count. The panel previews the
|
|
36
|
+
field at each stage: noise, output, blur.
|
|
37
|
+
- **Saved sketch presets.** Any set of dials saves under a name and reloads
|
|
38
|
+
later, as files under `<dataDir>/sketch-presets/` served by a new
|
|
39
|
+
`/api/sketch-presets` route on the dev plugin. A sketch look is a draft
|
|
40
|
+
effect, never part of a theme: it has no active/production pointer, it is not
|
|
41
|
+
adopted, and it never reaches `tokens.generated.css`. The shipped seven stay
|
|
42
|
+
in code, so the directory holds nothing but your own files.
|
|
43
|
+
- **A page can hand the layer its own elements.** The effect displaces boxes, so
|
|
44
|
+
a rule drawn as a `border` is not one of them. `--sketch-fill`,
|
|
45
|
+
`--sketch-stroke`, `--sketch-hatch-color` and `--sketch-radius` name what an
|
|
46
|
+
element should be drawn with, and `--sketch-icon-off: none` opts a subtree
|
|
47
|
+
out. The demo app's kit section draws its rules this way; the editor's own
|
|
48
|
+
overlay bar opts out, because the effect is for the page being designed and
|
|
49
|
+
not for the tool looking at it.
|
|
50
|
+
- **A Sketch mode chapter in the user guide.** It sits after Editing tokens and
|
|
51
|
+
covers the presets, the dials, and the `--sketch-*` properties a page uses to
|
|
52
|
+
hand the layer its own elements. Editing tokens itself now names all four
|
|
53
|
+
views; it had been describing two since the Colors view landed.
|
|
54
|
+
- **Sketches ships as an eighth preset theme.** A whole look built on the
|
|
55
|
+
effect: Cabin Sketch over Shantell Sans, square corners, and component
|
|
56
|
+
aliases tuned for a page that is drawn rather than rendered. Load it from the
|
|
57
|
+
Theme panel like any other preset. It stands on its own with Sketch mode off,
|
|
58
|
+
and the effect is what it was designed under.
|
|
59
|
+
- **The gradient library is open-ended.** `--gradient-N` was a fixed four-slot
|
|
60
|
+
scale; the Gradients section now has Add and Remove, and any number of
|
|
61
|
+
numbered slots loads from a theme file. A new slot seeds from the last one, so
|
|
62
|
+
it lands as a gradient you edit rather than an invisible transparent one.
|
|
63
|
+
- **A gradient can point at a corner.** Alongside degrees, a linear gradient
|
|
64
|
+
takes CSS's `to top right` and its seven neighbours. A keyword angles the
|
|
65
|
+
gradient line off the box's own diagonal, so it tracks the element's aspect
|
|
66
|
+
where a fixed angle cannot: `to bottom right` reads as about 95deg across a
|
|
67
|
+
wide heading and about 111deg once that heading wraps. The degrees underneath
|
|
68
|
+
are kept, so clearing the keyword lands on the nearest angle rather than
|
|
69
|
+
snapping to 0deg.
|
|
70
|
+
- **`--gradient-N-stops`.** Each slot now also emits its stop list on its own,
|
|
71
|
+
so a consumer can keep the theme's colours and supply their own geometry:
|
|
72
|
+
`linear-gradient(to top, var(--gradient-5-stops))`. One set of stops then
|
|
73
|
+
serves every direction a design needs, instead of a token per angle.
|
|
74
|
+
- **The editorial type role.** A fifth font stack (`--font-editorial`) and a
|
|
75
|
+
ninth text-style bundle (`--editorial-*`), for the long-reading surfaces that
|
|
76
|
+
should not carry the body face under an expressive display face. Both default
|
|
77
|
+
to indirections rather than literals: the stack resolves to `var(--font-sans)`
|
|
78
|
+
and the bundle mirrors `--body-md-*`, so a project that never mentions
|
|
79
|
+
editorial renders byte-identically. `live-tokens set-fonts` gained a matching
|
|
80
|
+
`editorial` slot, and the stack is editable in the editor beside the other
|
|
81
|
+
four.
|
|
82
|
+
|
|
83
|
+
### Changed
|
|
84
|
+
|
|
85
|
+
- **Derived palette values serialize unclamped.** A palette's basis is OKLCH,
|
|
86
|
+
and clamping every derived step into sRGB on the way out threw away chroma a
|
|
87
|
+
wide-gamut display can show. Values already inside sRGB serialize identically,
|
|
88
|
+
so nothing moves in an existing theme; intent authored beyond sRGB now
|
|
89
|
+
survives to the browser, which does its own gamut mapping at paint. The hex
|
|
90
|
+
readouts still show the clamped projection, which is what a hex readout is
|
|
91
|
+
for.
|
|
92
|
+
- **The product is spelled LiveTokens.** One word, in the README, the docs and
|
|
93
|
+
the demo app. The package name is unchanged.
|
|
94
|
+
- **A test fails on any engine load at module top.** `bin/engineLoadsLazily.test.ts`
|
|
95
|
+
follows every `.mjs` module a test suite can reach, transitively, and rejects
|
|
96
|
+
a top-level import of the compiled engine. CI runs the suite before it builds
|
|
97
|
+
the plugin, so such a load is a publish failure rather than a test failure.
|
|
98
|
+
This is the bug that took down 0.56.0.
|
|
99
|
+
|
|
100
|
+
### Fixed
|
|
101
|
+
|
|
102
|
+
- **A session persisted before the OKLCH palette basis no longer throws on
|
|
103
|
+
hydrate.** Such a session holds hex strings where every palette color is now
|
|
104
|
+
`{ l, c, h }`. `loadFromFile` migrated those on the way in and `hydrate` did
|
|
105
|
+
not, so the session reached the renderer with an undefined hue and threw on
|
|
106
|
+
the first serialization.
|
|
107
|
+
- **The overlay panel's chrome keeps its own font.** `tokens.css` sets the theme
|
|
108
|
+
font on `:where(*)`, and a matching rule beats inheritance, so the panel's
|
|
109
|
+
font-family never reached its children. The editor page already restored
|
|
110
|
+
inheritance for its chrome; the overlay now does the same.
|
|
111
|
+
|
|
112
|
+
### Migration
|
|
113
|
+
|
|
114
|
+
- Two **tokens.css migrations** ship here, both additive: `--font-editorial`
|
|
115
|
+
with the `--editorial-*` bundle, and a `--gradient-N-stops` companion per
|
|
116
|
+
gradient slot. Each companion is read out of the slot it belongs to rather
|
|
117
|
+
than hardcoded, so a retuned gradient does not get a stop list contradicting
|
|
118
|
+
it. Run `npx live-tokens migrate` to apply them to a vendored `tokens.css`, or
|
|
119
|
+
set the plugin's `autoMigrate` option and let it apply additive migrations on
|
|
120
|
+
boot. Until then the dev plugin warns on the gap and the new names simply
|
|
121
|
+
resolve to nothing.
|
|
122
|
+
- The **editorial font stack** is added to a theme file on load, cloned from
|
|
123
|
+
that theme's `--font-sans`. It is presence-based and idempotent, so there is
|
|
124
|
+
no schema step and a theme that never touches editorial keeps rendering as it
|
|
125
|
+
did.
|
|
126
|
+
|
|
127
|
+
## 0.56.1 — Release fix
|
|
128
|
+
|
|
129
|
+
### Fixed
|
|
130
|
+
|
|
131
|
+
- **The 0.56.0 publish failed in CI and never reached npm.** `scripts/lib/presetFonts.mjs`
|
|
132
|
+
loaded the compiled font-pairing engine at import time, and a vitest suite
|
|
133
|
+
imports that module for its `PRESET_FONTS` table; CI runs the tests before
|
|
134
|
+
it builds the plugin. The engine now loads inside `stampPresetFonts`, the
|
|
135
|
+
one caller that needs it. Everything listed under 0.56.0 ships here.
|
|
136
|
+
|
|
137
|
+
## 0.56.0 — Type is a first-class half of a theme
|
|
138
|
+
|
|
139
|
+
### Added
|
|
140
|
+
|
|
141
|
+
- **`live-tokens set-fonts` and the `live-tokens-pair-fonts` skill.** A theme's
|
|
142
|
+
type can now be chosen the way its color already could: describe the voice you
|
|
143
|
+
want and get a verified Google Fonts pairing bound to `--font-display`,
|
|
144
|
+
`--font-sans`, `--font-serif` and `--font-mono`. The skill carries the
|
|
145
|
+
reasoning (anchor on the body face, classify both candidates by form model,
|
|
146
|
+
apply the font matrix, gate every candidate on screen legibility); the CLI
|
|
147
|
+
does the verifying and the writing. Like `adjust`, it edits the unsaved
|
|
148
|
+
colors-and-type buffer, so a retype is an edit you keep by saving the open
|
|
149
|
+
theme. Color, component aliases, `tokens.css` and `fonts.css` are untouched.
|
|
150
|
+
- **URLs are negotiated from the family's real weights, not guessed.** A 200
|
|
151
|
+
from the Google Fonts API never proved weight coverage: the API silently drops
|
|
152
|
+
enumerated weights a family lacks and only rejects a *range* its axis cannot
|
|
153
|
+
serve. `set-fonts` now takes a census from the returned CSS and builds the
|
|
154
|
+
narrowest URL that delivers everything the family has: a range for a variable
|
|
155
|
+
family, an enumeration for a static one, a bare URL for a single-weight
|
|
156
|
+
display face. It also reports the weights your typography tokens ask for and
|
|
157
|
+
the family does not have.
|
|
158
|
+
- **`generate-theme` owns the whole look.** A theme is three decisions made
|
|
159
|
+
from one brief: color, type, and geometry. The skill reads the brief once,
|
|
160
|
+
names its voice, seeds the color, then invokes `live-tokens-pair-fonts` and
|
|
161
|
+
`live-tokens-adjust-geometry` with the same voice, so a moody night theme
|
|
162
|
+
arrives with type and corners to match rather than with the previous look's.
|
|
163
|
+
The three CLIs stay separate, so any one decision retunes without re-rolling
|
|
164
|
+
the others.
|
|
165
|
+
|
|
166
|
+
### Changed (breaking)
|
|
167
|
+
|
|
168
|
+
- **`live-tokens-adjust-shape-space` is now `live-tokens-adjust-geometry`.**
|
|
169
|
+
Same skill, same `adjust` verb; the name now matches the heading the token
|
|
170
|
+
suffix vocabulary already uses for radius, padding, gap, and border width.
|
|
171
|
+
Re-run `npx live-tokens setup-claude --force` to pick it up, then delete
|
|
172
|
+
`.claude/skills/live-tokens-adjust-shape-space/` by hand: `setup-claude`
|
|
173
|
+
never removes a directory, and the stale copy would keep triggering under
|
|
174
|
+
the old name.
|
|
175
|
+
|
|
176
|
+
### Changed
|
|
177
|
+
|
|
178
|
+
- **Skills are leaner and read the package instead of copying it.** The
|
|
179
|
+
create-component skill no longer inlines the shipped `Toggle` (the copy had
|
|
180
|
+
drifted 174 lines from its source); it points at the files in
|
|
181
|
+
`node_modules` and moves the linked-siblings, intrinsics, and fixed-overlay
|
|
182
|
+
material into reference files read on demand. The theme skill moved its
|
|
183
|
+
holiday anchors the same way. Every skill body is now under 250 lines.
|
|
184
|
+
- **The picker catalogue lists `Panel` and `InlineEditActions`.** Both shipped
|
|
185
|
+
without an entry, so the picker could never recommend them.
|
|
186
|
+
- **`npm run check:skills` gates the bundle.** It asserts the catalogue names
|
|
187
|
+
every shipped component, every reference file is pointed at and present,
|
|
188
|
+
every CLI verb a skill mentions exists, every skill has a sample prompt, and
|
|
189
|
+
no skill pastes a long file inline.
|
|
190
|
+
|
|
191
|
+
### Fixed
|
|
192
|
+
|
|
193
|
+
- **Adding a Google font by name in the editor no longer persists a dead URL.**
|
|
194
|
+
The by-name field built a `wght@100..900` range URL and never checked it, so
|
|
195
|
+
any family without that exact variable axis (every static family, every
|
|
196
|
+
single-weight display face) was saved with a URL the API answers 400 to. It
|
|
197
|
+
now runs the same negotiation `set-fonts` does, reports the family's real
|
|
198
|
+
weights, and fails loudly for a family that is not on Google Fonts.
|
|
199
|
+
|
|
3
200
|
## 0.55.1 — The anchored step is the base color
|
|
4
201
|
|
|
5
202
|
### Fixed
|