@motion-proto/live-tokens 0.72.1 → 0.74.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-build-page/SKILL.md +37 -2
- package/.claude/skills/live-tokens-build-page/references/layout-sources.md +48 -0
- package/.claude/skills/live-tokens-check-compliance/SKILL.md +2 -2
- package/.claude/skills/live-tokens-create-component/SKILL.md +4 -4
- package/.claude/skills/live-tokens-create-theme/SKILL.md +80 -0
- package/.claude/skills/live-tokens-create-theme/references/design-directions.md +94 -0
- package/.claude/skills/live-tokens-pick-component/SKILL.md +1 -1
- package/.claude/skills/live-tokens-set-colors/SKILL.md +140 -0
- package/.claude/skills/live-tokens-set-colors/references/color-anchors.md +80 -0
- package/.claude/skills/{live-tokens-adjust-geometry → live-tokens-set-geometry}/SKILL.md +12 -7
- package/.claude/skills/live-tokens-set-geometry/references/geometry-anchors.md +61 -0
- package/.claude/skills/{live-tokens-pair-fonts → live-tokens-set-type}/SKILL.md +18 -15
- package/.claude/skills/live-tokens-set-type/references/type-anchors.md +60 -0
- package/CHANGELOG.md +141 -0
- package/README.md +24 -15
- package/bin/check-page.mjs +3 -3
- package/bin/cli.mjs +92 -55
- package/bin/lib/liveState.mjs +110 -0
- package/bin/save-theme.mjs +177 -0
- package/bin/set-colors.mjs +191 -0
- package/bin/{adjust.mjs → set-geometry.mjs} +18 -50
- package/bin/{set-fonts.mjs → set-type.mjs} +21 -55
- package/dist-plugin/{chunk-RIXO2E55.js → chunk-7VRTBGJT.js} +1 -1
- package/dist-plugin/{chunk-YLCOIGQC.js → chunk-V3YF6CGT.js} +56 -2
- package/dist-plugin/index.cjs +58 -3
- package/dist-plugin/index.js +11 -11
- package/dist-plugin/migrateData/index.cjs +56 -1
- package/dist-plugin/migrateData/index.js +2 -2
- package/dist-plugin/{generateColorsAndType → setColors}/index.cjs +1109 -1071
- package/dist-plugin/{generateColorsAndType → setColors}/index.d.cts +33 -24
- package/dist-plugin/{generateColorsAndType → setColors}/index.d.ts +33 -24
- package/dist-plugin/{generateColorsAndType → setColors}/index.js +45 -63
- package/dist-plugin/{adjust → setGeometry}/index.cjs +60 -5
- package/dist-plugin/{adjust → setGeometry}/index.d.cts +1 -1
- package/dist-plugin/{adjust → setGeometry}/index.d.ts +1 -1
- package/dist-plugin/{adjust → setGeometry}/index.js +1 -1
- package/dist-plugin/{fontPairing → setType}/index.cjs +4 -4
- package/dist-plugin/{fontPairing → setType}/index.d.cts +1 -1
- package/dist-plugin/{fontPairing → setType}/index.d.ts +1 -1
- package/dist-plugin/{themeTypes-DSV3Zisf.d.cts → themeTypes-BxRtuN5V.d.cts} +1 -1
- package/dist-plugin/{themeTypes-DSV3Zisf.d.ts → themeTypes-BxRtuN5V.d.ts} +1 -1
- package/package.json +10 -2
- package/src/editor/core/themes/{generateColorsAndType.ts → buildColors.ts} +82 -96
- package/src/editor/core/themes/migrations/2026-09-03-drop-legacy-component-keys.ts +62 -0
- package/src/editor/core/themes/migrations/index.ts +2 -0
- package/src/editor/docs/content/creating-components.md +13 -0
- package/src/editor/docs/content/themes-workflow.md +2 -2
- package/src/editor/docs/content.generated.ts +2 -2
- package/src/editor/overlay/LiveEditorOverlay.svelte +519 -28
- package/src/editor/skill-atlas/SkillAtlas.svelte +836 -0
- package/src/editor/skill-atlas/SkillAtlas.svelte.d.ts +4 -0
- package/src/editor/skill-atlas/SourcePane.svelte +364 -0
- package/src/editor/skill-atlas/TreeNodeCard.svelte +206 -0
- package/src/editor/skill-atlas/skillSources.generated.ts +45 -0
- package/src/editor/skill-atlas/skillSources.ts +1 -0
- package/src/editor/skill-atlas/skillTrees.ts +3844 -0
- package/src/editor/skill-atlas/types.ts +65 -0
- package/src/live-tokens/data/colors-and-type/autumn.json +1 -37
- package/src/live-tokens/data/colors-and-type/default.json +1 -37
- package/src/live-tokens/data/colors-and-type/halloween.json +1 -37
- package/src/live-tokens/data/colors-and-type/midnight-study.json +1 -37
- package/src/live-tokens/data/colors-and-type/ocean.json +1 -37
- package/src/live-tokens/data/colors-and-type/royal-velvet.json +1 -37
- package/src/live-tokens/data/colors-and-type/sketchy.json +1 -37
- package/src/live-tokens/data/colors-and-type/spring-meadow.json +1 -37
- package/src/live-tokens/data/colors-and-type/sunset.json +1 -37
- package/src/live-tokens/data/themes/autumn.json +1 -37
- package/src/live-tokens/data/themes/halloween.json +1 -37
- package/src/live-tokens/data/themes/midnight-study.json +1 -37
- package/src/live-tokens/data/themes/ocean.json +1 -37
- package/src/live-tokens/data/themes/royal-velvet.json +1 -37
- package/src/live-tokens/data/themes/sketchy.json +1 -37
- package/src/live-tokens/data/themes/spring-meadow.json +1 -37
- package/src/live-tokens/data/themes/sunset.json +1 -37
- package/src/live-tokens/data/tokens.generated.css +0 -36
- package/.claude/skills/live-tokens-generate-theme/SKILL.md +0 -156
- package/.claude/skills/live-tokens-generate-theme/references/mood-vocabulary.md +0 -43
- package/.claude/skills/live-tokens-generate-theme/references/named-themes.md +0 -18
- package/.claude/skills/live-tokens-generate-theme/references/style-vocabulary.md +0 -35
- package/bin/generate-theme.mjs +0 -260
- /package/dist-plugin/{fontPairing → setType}/index.js +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: live-tokens-build-page
|
|
3
|
-
description: Apply the @motion-proto/live-tokens project conventions when building a page: shipped components, theme tokens over hex/pixel literals, dynamic route mounting, per-page site.css. Use when the user asks to build, create,
|
|
3
|
+
description: Apply the @motion-proto/live-tokens project conventions when building a page: shipped components, theme tokens over hex/pixel literals, dynamic route mounting, per-page site.css. Use when the user asks to build, create, lay out, or rearrange a page, route, hero, landing page, dashboard, settings screen, pricing page, or a tool screen with a stage and controls; add a route; place an existing component on a page; assemble a screen from the catalogue; or says the layout, label sizes, or control sizes of a page are off. For component choice see live-tokens-pick-component; for a brand-new component, live-tokens-create-component; for look and feel mid-build, live-tokens-create-theme or live-tokens-set-geometry.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Building pages in a live-tokens project
|
|
@@ -8,7 +8,7 @@ description: Apply the @motion-proto/live-tokens project conventions when buildi
|
|
|
8
8
|
Two rules above all else:
|
|
9
9
|
|
|
10
10
|
1. **Use a shipped component if one fits.** Import from `@motion-proto/live-tokens/components/<Name>.svelte`. See **live-tokens-pick-component** for the catalogue and the confusing-pair decisions. Pass only the props it declares, with variant and size values from its union: `npx live-tokens components <id>` prints them (`--json` for data), and the list includes the project's own components beside the shipped ones. A prop a component does not declare is dropped silently at runtime, and the checker reports it. Author custom markup only when nothing fits, and then consider **live-tokens-create-component** so the new piece is editable too.
|
|
11
|
-
2. **Use theme tokens for every value.** Every color, spacing, radius, font-size, and font-family in page CSS is a `var(--token-*)`, whether it sits in the `<style>` block, an inline `style=` attribute, or a `style:` directive. No colour literals in any notation, `white` and `rgb()` included. No px or rem in spacing, stroke, radius, or shadow: that is the geometry the theme owns and `
|
|
11
|
+
2. **Use theme tokens for every value.** Every color, spacing, radius, font-size, and font-family in page CSS is a `var(--token-*)`, whether it sits in the `<style>` block, an inline `style=` attribute, or a `style:` directive. No colour literals in any notation, `white` and `rgb()` included. No px or rem in spacing, stroke, radius, or shadow: that is the geometry the theme owns and `set-geometry` moves. Sizing is layout, not theme: a hero's height, a max content width, or a column's minimum width stays a literal. A change in `/live-tokens/editor` should repaint your page.
|
|
12
12
|
|
|
13
13
|
For text, reach for a whole text style rather than assembling one: `--heading-xl` through `--heading-sm`, `--body-md`, `--body-sm`, `--editorial-xl` through `--editorial-sm`, `--eyebrow`, and `--code` each carry a `-font-family`, `-font-size`, `-font-weight`, `-line-height`, and `-letter-spacing`. A heading set from `--heading-lg-*` retypes when the theme's fonts change; one set from a raw `font-size` does not.
|
|
14
14
|
|
|
@@ -16,10 +16,40 @@ Text inside a `Card` or a `CollapsibleSection` is typed by that container, not b
|
|
|
16
16
|
|
|
17
17
|
## Layout
|
|
18
18
|
|
|
19
|
+
**The purpose of a layout.** The page shows one thing. All other content must stay out of its way. Each mark that is not content costs attention: a rule, a border, a header bar, a shadow. Each mark must do a job that no other mark does.
|
|
20
|
+
|
|
21
|
+
Separate elements with the smallest difference that separates them. Use space first. If space is not sufficient, add a hairline rule. If a rule is not sufficient, use a second surface. Do not stack these separators. Two heavy edges side by side make a third shape between them. A band of boxes with borders and header bars looks like a set of posters.
|
|
22
|
+
|
|
23
|
+
Put each element in one of three layers, and type it from that layer. Content is `--text-primary`. Labels are `--eyebrow-*` or `--text-secondary`. Scaffolding is `--border-neutral`.
|
|
24
|
+
|
|
25
|
+
Show related items side by side when the width permits. Do not put them behind a toggle.
|
|
26
|
+
|
|
27
|
+
On a tool page, the stage is the content. Each control is administration. Give the space to the stage. Give the controls the smallest size that still works.
|
|
28
|
+
|
|
29
|
+
`references/layout-sources.md` names the sources for these laws.
|
|
30
|
+
|
|
31
|
+
Decide the bands before the columns. Read the page top to bottom and name each band by its job: what the user looks at, what they type into, what they press. A content page runs hero, sections, footer. A tool page runs the stage on top (the canvas, player, or strip the work is about), the inputs under it, and one toolbar of actions along the bottom edge. Each band is a row of the page grid; a band that needs columns of its own spans the grid and redeclares it, as below.
|
|
32
|
+
|
|
33
|
+
Separate bands with space and a rule, `padding-top: var(--space-16)` and `border-top: var(--border-width-1) solid var(--border-neutral)`, and stretch a band's boxes to one height (`align-items: stretch`) so their bottom edges make one line. Card chrome does not separate bands.
|
|
34
|
+
|
|
19
35
|
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
36
|
|
|
21
37
|
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
38
|
|
|
39
|
+
### Containers by job
|
|
40
|
+
|
|
41
|
+
- `Panel` is a stage: a canvas, a player, a preview. It pins its height so the page holds still while what it shows changes.
|
|
42
|
+
- `Card` is a titled block of content. Its header is typed by the card's own tokens, `--card-default-title-*` at `--font-size-2xl` with a body at `--font-size-xl` by default; `size="compact"` drops the title to md, the body to sm, and tightens the padding. That is a content card's voice, and the theme editor retunes it for the whole project.
|
|
43
|
+
- A box in a tool UI labels itself. Use `variant="bare" size="compact"` and put your own label in the body, typed from a text style: the `.eyebrow` class from `site.css` for a quiet section label, `.heading-sm` for one that leads. Leave the shipped header alone rather than shrinking it with a page rule.
|
|
44
|
+
- A toolbar is a flex row of small buttons on the band's bottom edge, grouped left and right with `justify-content: space-between`. No card around it.
|
|
45
|
+
|
|
46
|
+
### Density
|
|
47
|
+
|
|
48
|
+
- `Button` and `IconButton` take `size="small"` in toolbars, compose rows, and any band that holds more than a couple of actions; the default size is for the page's primary action. `fullWidth` belongs to a stacked rail and comes off in a row.
|
|
49
|
+
- A project component that wraps shipped buttons forwards a `size` prop to them, so a page sets density the same way for shipped and custom pieces.
|
|
50
|
+
- Text in your own elements inside a `Card` inherits the card's body size unless you type it. A label, count, or status line inside a card sets a text style of its own (`--body-sm-*`, `--code-*`).
|
|
51
|
+
- `MenuSelect` renders its list open. For a picker, toggle it from a small `Button` with a trailing chevron (`icon="fa-solid fa-chevron-down" iconPosition="right"`) and position the list absolutely under the button, `top: 100%` with a `--space-*` margin.
|
|
52
|
+
|
|
23
53
|
## Wiring
|
|
24
54
|
|
|
25
55
|
- Add the route the way `App.svelte` already wires routes:
|
|
@@ -48,6 +78,7 @@ const pages = {
|
|
|
48
78
|
- Colour literals, and px or rem in spacing, stroke, radius, or shadow.
|
|
49
79
|
- Hardcoded page-grid counts (`repeat(10, 1fr)`). Use `repeat(var(--columns-count), 1fr)`, or `calc(var(--columns-count) - 2)` for a sub-grid that spans fewer page columns. A local two-up or three-up is a layout and is fine.
|
|
50
80
|
- Utility classes overriding shipped components. Extend via the `/live-tokens/components` editor instead.
|
|
81
|
+
- A card header as a section label in a tool UI, and a page rule that shrinks it. Label the box yourself with a text style.
|
|
51
82
|
- Deep imports from `node_modules/@motion-proto/live-tokens/src/...`. Use public entry points only.
|
|
52
83
|
- Mounting `Editor` or `ComponentEditorPage` outside their dedicated routes.
|
|
53
84
|
- A page route under `/live-tokens/*`. That namespace is reserved for the package's own dev surfaces so they can never shadow your routes; the rest of the URL space is yours.
|
|
@@ -65,4 +96,8 @@ It fails on a component outside the catalogue, a prop or value the component doe
|
|
|
65
96
|
|
|
66
97
|
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
98
|
|
|
99
|
+
The checker cannot see a layout. Open the page at the width it is built for and read it band by band: the boxes in a band end on one line, no label is larger than the page's body copy, every control stays inside its box (a `width: 100%` field without `box-sizing: border-box` pushes past it by its padding), and the actions sit where the eye goes last. Fix what you see before you move on.
|
|
100
|
+
|
|
101
|
+
Then look at the page from a distance. The bands and their edges must be the only shapes that you see. Then look closely. For each border, header bar, and box, ask this question: does the page lose information if this element is removed? If the answer is no, remove the element. Find the element that a reader sees first, second, and third. Make sure that this is the reading order the page needs.
|
|
102
|
+
|
|
68
103
|
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`.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Layout sources
|
|
2
|
+
|
|
3
|
+
Read this when a layout decision in SKILL.md needs its reason. Each law in the
|
|
4
|
+
Layout section comes from one of these sources. The sources are for layout and
|
|
5
|
+
hierarchy only. Do not take color or type opinions from them: the theme owns
|
|
6
|
+
those.
|
|
7
|
+
|
|
8
|
+
## Edward Tufte
|
|
9
|
+
|
|
10
|
+
Tufte wrote about information graphics. His laws apply to a page because a page
|
|
11
|
+
is an information display with controls on it.
|
|
12
|
+
|
|
13
|
+
| Law | Statement | Rule in SKILL.md |
|
|
14
|
+
|---|---|---|
|
|
15
|
+
| Smallest effective difference | Make all visual distinctions as subtle as possible, but still clear and effective. | Separate with space first, then a hairline rule, then a second surface. |
|
|
16
|
+
| 1+1=3 | Two heavy marks side by side make a third mark: the space between them. | A band of boxes with borders and header bars looks like a set of posters. |
|
|
17
|
+
| Layering and separation | Put data on top, labels next, and scaffolding faintest. | Content, labels, and scaffolding each take their own token. |
|
|
18
|
+
| Administrative debris | The metaphor for the interface is the information. Remove the chrome that the tool adds for itself. | The stage takes the space. Controls take the smallest size that still works. |
|
|
19
|
+
| Spatial over temporal | Show information adjacent in space, not stacked in time behind controls. | Show related items side by side. Frames in a strip are small multiples. |
|
|
20
|
+
| Erase non-data ink | Remove each mark that carries no information. | The Verify question: does the page lose information if this element is removed? |
|
|
21
|
+
| Micro and macro readings | A good display reads at a distance and up close. | Verify from a distance, then closely. |
|
|
22
|
+
|
|
23
|
+
Sources:
|
|
24
|
+
|
|
25
|
+
- Envisioning Information (1990): layering and separation, small multiples, micro and macro. https://www.edwardtufte.com/book/envisioning-information/
|
|
26
|
+
- The Visual Display of Quantitative Information (1983): data-ink, chartjunk.
|
|
27
|
+
- iPhone interface design, edwardtufte.com notebook: administrative debris, spatial over temporal. https://www.edwardtufte.com/notebook/iphone-interface-design/
|
|
28
|
+
|
|
29
|
+
## Josef Müller-Brockmann
|
|
30
|
+
|
|
31
|
+
Grid Systems in Graphic Design (1981) is the discipline behind the page column
|
|
32
|
+
grid. The grid does the separating, so an element needs no border to show
|
|
33
|
+
where it sits. His stated aim is compact planning, intelligibility, and
|
|
34
|
+
clarity. That is Tufte's aim in a typographer's words.
|
|
35
|
+
|
|
36
|
+
## Refactoring UI
|
|
37
|
+
|
|
38
|
+
Adam Wathan and Steve Schoger, Refactoring UI (2018), turns both into working
|
|
39
|
+
rules for product screens:
|
|
40
|
+
|
|
41
|
+
- Put more space around a group than within it.
|
|
42
|
+
- Start with too much white space, then remove some.
|
|
43
|
+
- Use fewer borders. Separate with space, a shadow, or a second background.
|
|
44
|
+
- Emphasize by de-emphasizing the secondary content.
|
|
45
|
+
- Labels are a last resort.
|
|
46
|
+
- Keep a spacing scale where no two steps are closer than a quarter. The `--space-*` scale is that scale.
|
|
47
|
+
|
|
48
|
+
https://www.refactoringui.com/
|
|
@@ -27,7 +27,7 @@ The answer to "check this project" is a report. Every fact in it comes from one
|
|
|
27
27
|
| `usage.byPage` | Which catalogue component each page renders, and how many times | A page rendering none is either chrome or hand-rolled markup that a shipped component covers. |
|
|
28
28
|
| `usage.unusedShipped` | Shipped components no page renders | Information, not a finding. |
|
|
29
29
|
| `usage.customUnregistered`, `usage.customUnused` | The project's own components that are unregistered or unused | Dead or half-wired work. |
|
|
30
|
-
| `findings.pages`, `findings.components` | Both checkers' findings by rule, under the project's severities and again
|
|
30
|
+
| `findings.pages`, `findings.components` | Both checkers' findings by rule, under the project's severities and again with every warning counted as an error | The errors are what fails the build today; the strict count is what a fully tokenized project would fail. |
|
|
31
31
|
|
|
32
32
|
## Mechanical or judgement
|
|
33
33
|
|
|
@@ -42,7 +42,7 @@ A translucent overlay on an app shell, or a layout size the project owns, may be
|
|
|
42
42
|
|
|
43
43
|
1. Migrations pending, and the one command that clears them.
|
|
44
44
|
2. What fails the build now: errors by rule, with the files.
|
|
45
|
-
3. What
|
|
45
|
+
3. What the strict count adds: warnings by rule.
|
|
46
46
|
4. Components: unread tokens, unregistered, undescribed.
|
|
47
47
|
5. Usage: what each page renders, and what is used nowhere.
|
|
48
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.
|
|
@@ -49,7 +49,7 @@ Shipped editors live in `src/editor/component-editor/` because they are library-
|
|
|
49
49
|
```bash
|
|
50
50
|
npx live-tokens check-component <id> --strict --json
|
|
51
51
|
```
|
|
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`.
|
|
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. `--off=<rule>` silences a rule for one run, which a component still being authored has no use for: the finding is a decision to make. 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
53
|
|
|
54
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.
|
|
55
55
|
7. **Verify** with the checklist at the bottom of this file, then place the component on a page with **live-tokens-build-page**.
|
|
@@ -90,9 +90,9 @@ state-after-property and fails.
|
|
|
90
90
|
|
|
91
91
|
Read `references/token-naming.md` for what each one means and when two of them
|
|
92
92
|
compete. A suffix outside that list fails `check-component`. The list lives in
|
|
93
|
-
`KIND_RULES` in the editor's `aliasKinds.ts`, which the picker, the
|
|
94
|
-
CLI, and `check-component` all read, so a name accepted here
|
|
95
|
-
control behind it.
|
|
93
|
+
`KIND_RULES` in the editor's `aliasKinds.ts`, which the picker, the
|
|
94
|
+
`set-geometry` CLI, and `check-component` all read, so a name accepted here
|
|
95
|
+
always has a control behind it.
|
|
96
96
|
|
|
97
97
|
### Rules that bite
|
|
98
98
|
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: live-tokens-create-theme
|
|
3
|
+
description: Create a complete live-tokens theme from a natural-language request by stating one design direction and routing a color intent, a type intent, and a geometry intent to live-tokens-set-colors, live-tokens-set-type, and live-tokens-set-geometry. Use whenever the user asks for a theme, look, vibe, or brand feel by mood, style, era, season, holiday, or hue; when they name only a color and want a theme around it; or when they refine a look across more than one dimension. Not for a single token (use the editor), and not for one dimension alone: color is live-tokens-set-colors, type is live-tokens-set-type, geometry is live-tokens-set-geometry.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Creating a theme from a request
|
|
7
|
+
|
|
8
|
+
A look is three decisions: color, type, and geometry. This skill reads the
|
|
9
|
+
**request**, the user's own words, and states one **design direction**, a line
|
|
10
|
+
or two that fixes all three. From it come three **intents**, one per dimension,
|
|
11
|
+
each naming an outcome and never a value. Each goes to the contributing skill
|
|
12
|
+
that owns that dimension, and their three reports come back as one **assembled
|
|
13
|
+
report**, so the whole look comes from one reading.
|
|
14
|
+
|
|
15
|
+
Every contributing skill writes its dimension into the unsaved buffers the app
|
|
16
|
+
already renders, and those three buffers are the **look**. This skill runs one
|
|
17
|
+
CLI of its own, `save-theme`, which turns the look into the **theme**, the
|
|
18
|
+
document at `themes/<slug>.json`, and opens it. Never hand-author theme JSON and
|
|
19
|
+
never edit the data tree directly.
|
|
20
|
+
|
|
21
|
+
## Workflow
|
|
22
|
+
|
|
23
|
+
1. Read the request once and state the design direction to the user: the mood, the hue family, the scheme, and the type and geometry that mood implies. It fixes enough to derive the three intents in step 3, and it names the default where the request leaves a dimension open. Keep it to a line or two. Every step below keys off it.
|
|
24
|
+
2. Read `references/design-directions.md` and name the **anchor** the request matches: a feeling, an idiom, or an occasion that reference lists, each one fixing color, type, and geometry together. An idiom sets constraints and a feeling moves dials inside them, so a request matching both reads the idiom first. A request matching none takes the design direction alone.
|
|
25
|
+
3. State the three intents the design direction and the anchor imply, one line each: the color intent, the type intent, and the geometry intent. Each names an outcome. Pass the anchor's name with each one, because every contributing skill holds its own anchors for its own dimension under the same names. Never reach for an OKLCH triple, a font family, or a token on a contributing skill's behalf.
|
|
26
|
+
4. Invoke **live-tokens-set-colors** with the color intent. This step never skips: a theme request names a color identity, so color is the one dimension every look fixes.
|
|
27
|
+
5. Invoke **live-tokens-set-type** with the type intent. Skip only when the user asked to leave the type alone.
|
|
28
|
+
6. Invoke **live-tokens-set-geometry** with the geometry intent. Skip when the geometry intent is to leave the geometry alone.
|
|
29
|
+
7. Take the theme name from the design direction and run `npx live-tokens save-theme "<name>"`. It composes the three buffers into `themes/<slug>.json` and opens it, so nothing is left unsaved. `--dry-run` prints what it would write.
|
|
30
|
+
8. Assemble the three reports into the assembled report: the design direction, what each contributing skill changed, the theme `save-theme` wrote, and anything one of them flagged. Tell the user to look at the running app. Offer refinements (see Refining a look).
|
|
31
|
+
|
|
32
|
+
A set of themes runs steps 4 to 7 once per theme, with `--no-activate` on every
|
|
33
|
+
save but the last, so each theme starts from the same live look.
|
|
34
|
+
|
|
35
|
+
## What each contributing skill owns
|
|
36
|
+
|
|
37
|
+
Hand an outcome and the anchor's name. The mechanics stay where they are.
|
|
38
|
+
|
|
39
|
+
| Dimension | Contributing skill | It decides |
|
|
40
|
+
|---|---|---|
|
|
41
|
+
| color | live-tokens-set-colors | ten base colors, the scheme, harmony, the canvas commitment, the contrast pass |
|
|
42
|
+
| type | live-tokens-set-type | the two families, the form models behind them, the weights |
|
|
43
|
+
| geometry | live-tokens-set-geometry | radius, padding, gap, and border-width moves, global or per component |
|
|
44
|
+
|
|
45
|
+
A dimension the request leaves open still gets an intent, taken from the anchor.
|
|
46
|
+
A dimension the request rules out gets no invocation at all, and the assembled
|
|
47
|
+
report says which.
|
|
48
|
+
|
|
49
|
+
## Refining a look
|
|
50
|
+
|
|
51
|
+
A refinement arrives against a theme that is already open, and one adjective
|
|
52
|
+
usually names one dimension. Route it rather than re-reading the whole look:
|
|
53
|
+
|
|
54
|
+
| The user says | Goes to |
|
|
55
|
+
|---|---|
|
|
56
|
+
| warmer, cooler, calmer, louder, lighter, darker, moodier, more contrast | live-tokens-set-colors |
|
|
57
|
+
| more editorial, friendlier, more technical, a serif for headings | live-tokens-set-type |
|
|
58
|
+
| rounder, sharper, pill buttons, tighter, airier, thicker borders | live-tokens-set-geometry |
|
|
59
|
+
|
|
60
|
+
Keep this skill for a refinement that spans dimensions ("make it feel more
|
|
61
|
+
serious"), or one that names no dimension at all. State a new design direction
|
|
62
|
+
and route all three again.
|
|
63
|
+
|
|
64
|
+
## Files each step writes
|
|
65
|
+
|
|
66
|
+
Color, type, and geometry each write an unsaved buffer, which the page already
|
|
67
|
+
runs. `save-theme` composes the three into `themes/<slug>.json` and opens it,
|
|
68
|
+
which clears the buffers; Adopt then ships the theme. Opening a theme never
|
|
69
|
+
changes what the site ships. Only Adopt, in the editor, does that. Component
|
|
70
|
+
aliases and gradients carry forward from the live look into the theme
|
|
71
|
+
`save-theme` writes; user-tuned gradients survive, stock ones rebuild from the
|
|
72
|
+
new families.
|
|
73
|
+
|
|
74
|
+
## Verify
|
|
75
|
+
|
|
76
|
+
- Each contributing skill reports back, and `set-colors` exits 0 with every check passing (auto-corrected is fine).
|
|
77
|
+
- `save-theme` exits 0 and names the theme it wrote and opened.
|
|
78
|
+
- The app (dev server running) shows the whole look after a reload, and the editor's Theme panel names that theme with no unsaved marker.
|
|
79
|
+
- The assembled report names one design direction, and the three intents trace to it.
|
|
80
|
+
- To return to the previous look, load the earlier theme from the Theme panel.
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Design directions: feelings, idioms, and occasions
|
|
2
|
+
|
|
3
|
+
Read this once the request names a feeling, a design idiom, an era, a genre, a
|
|
4
|
+
holiday, a season, or a natural scene. Each entry places the request and gives
|
|
5
|
+
the direction the three intents come from.
|
|
6
|
+
|
|
7
|
+
The mechanics live with the executors. Color anchors are in
|
|
8
|
+
live-tokens-set-colors, type anchors in live-tokens-set-type, geometry anchors
|
|
9
|
+
in live-tokens-set-geometry, each keyed on the same names as the tables below.
|
|
10
|
+
Name the anchor when you state an intent and the sibling reads its own column.
|
|
11
|
+
|
|
12
|
+
Three axes place any request, including one no entry lists:
|
|
13
|
+
|
|
14
|
+
| Axis | Reads as | Carried by |
|
|
15
|
+
|---|---|---|
|
|
16
|
+
| Valence | pleasant against unpleasant | lightness, above everything else |
|
|
17
|
+
| Energy | aroused against calm | chroma, and hue distance on screen |
|
|
18
|
+
| Dominance | assertive against yielding | surface contrast, type weight, border weight, tightness |
|
|
19
|
+
|
|
20
|
+
An idiom sets constraints and a feeling moves dials, so a request that names
|
|
21
|
+
both ("cozy brutalist", "clinical Swiss") reads the idiom first and lets the
|
|
22
|
+
feeling move the dials inside it.
|
|
23
|
+
|
|
24
|
+
## Feelings
|
|
25
|
+
|
|
26
|
+
Valence and energy set the quadrant, and the table runs in quadrant order:
|
|
27
|
+
pleasant-aroused, pleasant-calm, unpleasant-aroused, unpleasant-calm. Dominance
|
|
28
|
+
separates confident from gentle inside one quadrant and lives almost entirely
|
|
29
|
+
outside color.
|
|
30
|
+
|
|
31
|
+
| Request | Placement | Direction |
|
|
32
|
+
|---|---|---|
|
|
33
|
+
| Joyful, exuberant, energetic | pleasant, high energy | warm and bright throughout, with nothing held back |
|
|
34
|
+
| Playful, whimsical | pleasant, high energy, low dominance | four hue families at play, soft and generous |
|
|
35
|
+
| Optimistic, hopeful | pleasant, moderate energy | a cool ground lit by one warm counterpoint, like sunrise |
|
|
36
|
+
| Confident, bold | pleasant, high energy, high dominance | wide contrast, heavy weight, held tight |
|
|
37
|
+
| Serene, tranquil | pleasant, low energy | cool and quiet, with nothing loud anywhere |
|
|
38
|
+
| Tender, gentle, romantic | pleasant, low energy, low dominance | a soft warm ground, a narrow range, light weights |
|
|
39
|
+
| Cozy, comforting | pleasant, low energy | warm through and through, nothing cool on screen |
|
|
40
|
+
| Wistful, nostalgic, vintage, faded | pleasant, low energy | chroma withheld rather than light withheld |
|
|
41
|
+
| Earthy, grounded, natural | pleasant, low energy, moderate dominance | warm mineral hues, nothing synthetic |
|
|
42
|
+
| Clinical, sterile, precise | neutral, low energy, high dominance | an untinted ground, one cool hue, tightly set |
|
|
43
|
+
| Contemplative, focused | neutral, low energy | one cool hue and almost nothing else |
|
|
44
|
+
| Urgent, alarming | unpleasant, high energy, high dominance | a neutral ground so the alarm lands, heavy and tight |
|
|
45
|
+
| Tense, anxious | unpleasant, high energy | an uncomfortable ground under a pair that vibrates |
|
|
46
|
+
| Defiant, rebellious, loud | unpleasant, high energy, highest dominance | near-black under one acid hue, blunt everywhere |
|
|
47
|
+
| Melancholy, moody, sad | unpleasant, low energy | dark and cool, holding one moment of color |
|
|
48
|
+
| Somber, grave, mournful | unpleasant, low energy, high dominance | near-neutral dark, sharp and quiet |
|
|
49
|
+
| Ominous, dramatic, haunted | unpleasant, low energy, high dominance | dark with one hot accent and real atmosphere |
|
|
50
|
+
| Austere, severe, cold | unpleasant, lowest energy, highest dominance | monochrome at one extreme of lightness |
|
|
51
|
+
|
|
52
|
+
## Idioms, eras, and genres
|
|
53
|
+
|
|
54
|
+
The table runs modernist, digital, quiet, print, expressive.
|
|
55
|
+
|
|
56
|
+
| Request | Placement | Direction |
|
|
57
|
+
|---|---|---|
|
|
58
|
+
| Swiss, International | neutral, low energy, high dominance | one hue on a near-white ground, rational, tight |
|
|
59
|
+
| Bauhaus | pleasant, high energy, high dominance | primaries at full commitment on paper, geometric, square but for the circle |
|
|
60
|
+
| Mid-century modern | pleasant, moderate energy | warm muted mid-tones, soft and open, no borders |
|
|
61
|
+
| Art deco, opulent, luxurious | pleasant, low energy, high dominance | dark with one metal, high-contrast type, sharp |
|
|
62
|
+
| Terminal, phosphor | neutral, moderate energy, high dominance | one phosphor hue on near-black, mono, bordered |
|
|
63
|
+
| Cyberpunk, neon noir, futuristic | unpleasant, high energy, high dominance | dark with two neons and a glow, wide type, sharp |
|
|
64
|
+
| Vaporwave | pleasant, moderate energy, low dominance | light sunset pastels with a gradient, retro display, soft |
|
|
65
|
+
| Y2K, bubble | pleasant, high energy | a chrome ground under electric color, geometric, pills |
|
|
66
|
+
| Blueprint | neutral, low energy, high dominance | a drafting ground with pale rules, technical type, gridded |
|
|
67
|
+
| Scandinavian, hygge | pleasant, low energy, low dominance | a chalk ground and muted naturals, soft and open |
|
|
68
|
+
| Japandi, wabi-sabi | pleasant, lowest energy | unbleached paper, near-monochrome, generous space, no borders |
|
|
69
|
+
| Cottagecore, botanical | pleasant, low energy, low dominance | warm cream and garden hues, serif display, soft |
|
|
70
|
+
| Editorial, magazine | neutral, low energy, high dominance | paper and ink with one strong hue, carried by rules |
|
|
71
|
+
| Newsprint, broadsheet | neutral, low energy | grey-warm paper under near-black ink, serif throughout, tight |
|
|
72
|
+
| Risograph, zine | pleasant, high energy, high dominance | two flat spot inks on paper, expressive display, heavy rules |
|
|
73
|
+
| Corporate, professional, trustworthy | pleasant, low energy | cool near-white with navy and teal, conventional everywhere |
|
|
74
|
+
| Brutalist | unpleasant, high energy, highest dominance | a pure ground, one alarming hue, heavy type, thick borders |
|
|
75
|
+
| Memphis, postmodern | pleasant, highest energy | a pastel ground under four hue families, shapes set against each other |
|
|
76
|
+
| Industrial, workshop, gritty | neutral, moderate energy, high dominance | concrete and steel with safety orange, condensed type, thick borders |
|
|
77
|
+
|
|
78
|
+
## Occasions
|
|
79
|
+
|
|
80
|
+
An occasion fixes color only, so its type and geometry intents come from the
|
|
81
|
+
feeling it implies or from the generic tables in the sibling skills.
|
|
82
|
+
|
|
83
|
+
Every occasion is a statement request: the named color goes on the ground
|
|
84
|
+
rather than only on the buttons.
|
|
85
|
+
|
|
86
|
+
| Request | Direction |
|
|
87
|
+
|---|---|
|
|
88
|
+
| Christmas | red and green with gold, one of the two owning the ground |
|
|
89
|
+
| Halloween | pumpkin, violet, and poison green, dark either way |
|
|
90
|
+
| St. Patrick's | green with gold over a pale ground |
|
|
91
|
+
| Ocean | blues held to one narrow band |
|
|
92
|
+
| Sunset | a hue sweep through red, falling in lightness |
|
|
93
|
+
| Autumn | parchment under rust, gold, and moss |
|
|
94
|
+
| Spring | pastels, greens and pinks over a mint ground |
|
|
@@ -39,7 +39,7 @@ All four pick one option from a set. The right one depends on **option count**,
|
|
|
39
39
|
| `SegmentedControl`| Inline switch between alternative *views of the same data* | Compact pill | 2–4 |
|
|
40
40
|
| `TabBar` | Switching between *tab panels* (content area swaps below) | Page-section | 2–7 |
|
|
41
41
|
| `RadioButton` | Form-style selection where the user reviews all options as text | Form-row | Any |
|
|
42
|
-
| `MenuSelect` |
|
|
42
|
+
| `MenuSelect` | A list of options, one checked; renders open, so a dropdown toggles it from a `Button` | Open list | Any |
|
|
43
43
|
|
|
44
44
|
- `TabBar` implies "this changes the page"; `SegmentedControl` implies "this is one knob among others."
|
|
45
45
|
- Use `RadioButton` when labels deserve room to breathe and the user is committing to a larger form.
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: live-tokens-set-colors
|
|
3
|
+
description: Set a live-tokens theme's color from a color intent: ten OKLCH base colors, a light or dark scheme, and an AA-gated contrast pass, written into the unsaved color buffer the app already renders. Use whenever the user asks for a palette, colors, or hues by mood, style, era, season, holiday, or hue; when they name only a color; or when they refine the color of a look: warmer, cooler, calmer, louder, lighter, darker, moodier, more contrast. Also invoked by live-tokens-create-theme, which supplies the color intent for a whole look. Changes color only, never fonts or geometry. Not for a single token (use the editor), and not for a whole look (see live-tokens-create-theme).
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Setting a theme's colors
|
|
7
|
+
|
|
8
|
+
You choose ten base colors; the CLI builds every ramp from them, enforces AA
|
|
9
|
+
contrast on the derived text tokens, writes the result into the unsaved colors
|
|
10
|
+
buffer the app already renders, and prints a contrast report. Never hand-author
|
|
11
|
+
theme JSON and never edit the data tree directly.
|
|
12
|
+
|
|
13
|
+
The run replaces the color state in that buffer and carries everything else
|
|
14
|
+
forward, so it composes with type and geometry in any order. Saving the open
|
|
15
|
+
theme in the editor, or running `save-theme`, turns the live look into a theme.
|
|
16
|
+
|
|
17
|
+
## Workflow
|
|
18
|
+
|
|
19
|
+
1. Read the color intent. When it names an anchor (a feeling, an idiom, or an occasion), read `references/color-anchors.md` for that entry; it overrides the generic bands below. Say which anchor you took.
|
|
20
|
+
2. Translate the intent into ten base colors using the framework below and write `scratch/<slug>-base-colors.json`. Nothing else records the base colors, so this file is the only copy; one per slug is what makes the refinement pass cheap.
|
|
21
|
+
3. Run `npx live-tokens set-colors scratch/<slug>-base-colors.json`. It writes the color state into the unsaved buffer the page already runs, and prints a contrast report.
|
|
22
|
+
4. Read the report. Exit 0 passes, and auto-corrected values count as passing. Exit 1 means the base colors are unworkable; each failure line names the base color to change, usually by raising its lightness or cutting its chroma. Fix the base color file and re-run.
|
|
23
|
+
5. Report back in a line: the scheme, the hue families on screen, the canvas commitment level, and anything the report auto-corrected.
|
|
24
|
+
|
|
25
|
+
Flags: `--dry-run` prints the contrast report without writing.
|
|
26
|
+
|
|
27
|
+
## The base color file
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"scheme": "light",
|
|
32
|
+
"baseColors": {
|
|
33
|
+
"Brand": { "l": 0.62, "c": 0.17, "h": 145 },
|
|
34
|
+
"Accent": { "l": 0.80, "c": 0.15, "h": 95 },
|
|
35
|
+
"Special": { "l": 0.60, "c": 0.19, "h": 300 },
|
|
36
|
+
"Canvas": { "l": 0.93, "c": 0.04, "h": 120 },
|
|
37
|
+
"Neutral": { "l": 0.55, "c": 0.012, "h": 140 },
|
|
38
|
+
"Alternate": { "l": 0.58, "c": 0.009, "h": 60 },
|
|
39
|
+
"Info": { "l": 0.60, "c": 0.15, "h": 255 },
|
|
40
|
+
"Success": { "l": 0.60, "c": 0.16, "h": 150 },
|
|
41
|
+
"Warning": { "l": 0.75, "c": 0.15, "h": 85 },
|
|
42
|
+
"Danger": { "l": 0.58, "c": 0.20, "h": 25 }
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
A base color is the one color a palette's whole ramp derives from. All 10 are required, and each may be given as a `"#rrggbb"` string instead. OKLCH: `l` is 0 to 1 lightness, `c` is chroma (0 grey, about 0.37 max), `h` is hue in degrees. The file names no theme: the slug in its own path is the theme name live-tokens-create-theme intends, or any label when this skill runs alone. `canvasGradient` is an optional boolean, see below.
|
|
48
|
+
|
|
49
|
+
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.
|
|
50
|
+
|
|
51
|
+
## Chroma budget: color is inversely proportional to area
|
|
52
|
+
|
|
53
|
+
| Tier | Palettes | Chroma |
|
|
54
|
+
|---|---|---|
|
|
55
|
+
| Ground (about 60% of every screen) | Neutral, Alternate | C 0.008 to 0.02 |
|
|
56
|
+
| Canvas (the largest single area) | Canvas | Per the commitment levels below, C 0.02 to 0.14 |
|
|
57
|
+
| Dominant chromatic (about 30%) | Brand | C 0.10 to 0.20 |
|
|
58
|
+
| Garnish (about 10%) | Accent, Special | may exceed Brand; at most one at the gamut cap for its hue (see Gamut guardrails) |
|
|
59
|
+
| Conditional | Info, Success, Warning, Danger | C 0.12 to 0.19 |
|
|
60
|
+
|
|
61
|
+
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 unless an anchor calls for it.
|
|
62
|
+
|
|
63
|
+
## Per-role bands
|
|
64
|
+
|
|
65
|
+
| Base color | Light scheme | Dark scheme | Hue |
|
|
66
|
+
|---|---|---|---|
|
|
67
|
+
| 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 |
|
|
68
|
+
| Neutral, Alternate | L about 0.55, C 0.008 to 0.02 | same | per the chroma budget |
|
|
69
|
+
| 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 request's identity hue |
|
|
70
|
+
| Accent | harmony slot, or at least 0.25 L from Brand when the mode collapses hue distance | lighten and desaturate like Brand | harmony slot |
|
|
71
|
+
| Special | most expressive; default Brand hue +60 at about 65% of Brand's C | same transform | harmony slot |
|
|
72
|
+
| Info | shared status L (0.55 to 0.65 light) | lighten like Brand | H 230 to 260 |
|
|
73
|
+
| Success | shared status L | same | H 140 to 155 |
|
|
74
|
+
| Warning | L 0.75 or higher (vivid yellow must be light) | same | H 70 to 90 |
|
|
75
|
+
| Danger | shared status L, C 0.15 to 0.20 | same | H 20 to 30 |
|
|
76
|
+
|
|
77
|
+
**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 intents and never the default. Three levels of commitment:
|
|
78
|
+
|
|
79
|
+
1. *Tinted paper* (most UI intents): C 0.02 to 0.06, with L down to 0.92 where the hue needs room.
|
|
80
|
+
2. *Colored ground* (expressive intents): L 0.85 to 0.92 at C 0.05 to 0.10. The page is unmistakably mint, parchment, sky.
|
|
81
|
+
3. *Full-color ground* (holiday and statement intents): 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.
|
|
82
|
+
|
|
83
|
+
Also:
|
|
84
|
+
|
|
85
|
+
- 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.
|
|
86
|
+
- 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.
|
|
87
|
+
- A dark scheme transforms every base color: each chromatic one lightens to L 0.75 to 0.85 and drops about a third of its chroma, because saturated color vibrates on dark grounds.
|
|
88
|
+
- 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.
|
|
89
|
+
- Status hues never rotate with the harmony; only their L and C adapt to the mood.
|
|
90
|
+
|
|
91
|
+
## Mood dials
|
|
92
|
+
|
|
93
|
+
Pleasantness rises with lightness (strongly) and saturation (weakly); energy rises with saturation; drama rises with dark plus saturated. Dominance, the third axis, is carried by surface contrast, type weight, and tightness rather than by color at all.
|
|
94
|
+
|
|
95
|
+
That is the whole mechanism, and one dial moves without a reference: warm is hues 20 to 110 plus pink 290 to 360, cool is 140 to 290. For an intent that names a feeling, read `references/color-anchors.md` instead of guessing the dial settings.
|
|
96
|
+
|
|
97
|
+
Avoid mid-lightness yellow-green (H 100 to 120 at L 0.5 to 0.7, C about 0.1) unless the intent asks for olive or toxic.
|
|
98
|
+
|
|
99
|
+
## Gamut guardrails
|
|
100
|
+
|
|
101
|
+
The engine clamps to gamut regardless; these keep the intent achievable.
|
|
102
|
+
|
|
103
|
+
- 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.
|
|
104
|
+
- 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.
|
|
105
|
+
- Teal and sky cap at C 0.15.
|
|
106
|
+
- 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.
|
|
107
|
+
|
|
108
|
+
## Harmony
|
|
109
|
+
|
|
110
|
+
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.
|
|
111
|
+
|
|
112
|
+
- A vague or single-adjective intent 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%.
|
|
113
|
+
- An intent naming two colors: measure their hue gap and pick the matching mode (green plus gold is 60 to 90 degrees, so analogous or compound).
|
|
114
|
+
- Drama or maximum contrast: complementary, triadic, or tetradic, and then tone one side down, since max-chroma text on a near-black ground vibrates.
|
|
115
|
+
|
|
116
|
+
## Canvas sky and shadows
|
|
117
|
+
|
|
118
|
+
`"canvasGradient": true` renders the page background as a vertical gradient from the Canvas ramp. Default off. Turn it on only when the intent evokes atmosphere (sky, night, dusk, glow, underwater) or asks for a gradient outright; keep it off for crisp, flat, minimal, or corporate intents 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 it is on, in one line.
|
|
119
|
+
|
|
120
|
+
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 base color's L.
|
|
121
|
+
|
|
122
|
+
## Refining the color of a theme that exists
|
|
123
|
+
|
|
124
|
+
"Warmer", "calmer", "more contrast" arrive against a theme that is already open, and the answer is a new base color file. Edit `scratch/<slug>-base-colors.json` when it is still there. When it is not, recover the base colors: `src/live-tokens/data/themes/<slug>.json` holds each one verbatim at `colorsAndType.editorConfigs.<Palette>.baseColor` as `{l, c, h}`, and the Canvas base color's lightness gives the scheme. Rebuild the base color file from those ten values, move the dial the user named, and re-run. A re-run replaces the buffer's whole color state, including palette edits made in the editor since the last run, so say so once when iterating; a Save or a `save-theme` run keeps the result.
|
|
125
|
+
|
|
126
|
+
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 base color 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.
|
|
127
|
+
|
|
128
|
+
## Scope
|
|
129
|
+
|
|
130
|
+
Color only. Type and geometry are untouched: `set-colors` replaces the color
|
|
131
|
+
state in the unsaved buffer and carries every other value in it forward. Save
|
|
132
|
+
the open theme in the editor, or run `save-theme`, to keep the result; Adopt
|
|
133
|
+
ships it.
|
|
134
|
+
|
|
135
|
+
## Verify
|
|
136
|
+
|
|
137
|
+
- The CLI exits 0 with every check passing (auto-corrected is fine), and the report names the layer it carried the rest of the look forward from.
|
|
138
|
+
- The app (dev server running) shows the new palette after a reload. The editor's Theme panel marks the open theme unsaved, unless the run was a dry one or the report says the layer under the buffer, the open theme or the package default, already holds these colors.
|
|
139
|
+
- The canvas is committed: on screen it reads as the theme's color rather than as generic near-white.
|
|
140
|
+
- To revert, re-run with the previous base color file, or load the open theme again to discard the buffer.
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Color anchors: feelings, idioms, and occasions
|
|
2
|
+
|
|
3
|
+
Read this when the color intent names one of these. Entries are starting
|
|
4
|
+
points: apply the chroma budget, the per-role bands, and the canvas commitment
|
|
5
|
+
rules from SKILL.md on top of them.
|
|
6
|
+
|
|
7
|
+
An idiom sets constraints and overrides the generic defaults in SKILL.md. The
|
|
8
|
+
polished-UI Accent at 45% of Brand's chroma is right for a vague intent and
|
|
9
|
+
wrong for Bauhaus. A feeling moves dials, and moves them inside an idiom's
|
|
10
|
+
constraints when the intent names both.
|
|
11
|
+
|
|
12
|
+
Energy spent on the ground tier fights the contrast gate, so keep chroma on the
|
|
13
|
+
garnish. A low-valence, low-energy intent taken literally reads as broken
|
|
14
|
+
rather than sad, which is why every dark entry below holds one moment of color.
|
|
15
|
+
|
|
16
|
+
Riso, Memphis, and brutalist break the chroma budget on purpose. Break it in
|
|
17
|
+
the one layer the style is about and hold the rest of the ground tier down.
|
|
18
|
+
|
|
19
|
+
## Feelings
|
|
20
|
+
|
|
21
|
+
| Anchor | Anchors (L, C, H) |
|
|
22
|
+
|---|---|
|
|
23
|
+
| Joyful, exuberant, energetic | butter canvas (0.95, 0.05, 90), Brand (0.80, 0.17, 75), coral Accent (0.72, 0.18, 20), green Special (0.75, 0.16, 145); analogous warm. Yellow stays yellow only above L 0.80 |
|
|
24
|
+
| Playful, whimsical | tinted canvas (0.93, 0.05, 330), Special at full chroma; tetradic, the rare request that wants four hue families |
|
|
25
|
+
| Optimistic, hopeful | sky canvas (0.94, 0.03, 220), Brand (0.62, 0.14, 200), warm yellow Accent (0.85, 0.14, 90); complementary across the warm/cool line, which reads as sunrise rather than sky |
|
|
26
|
+
| Confident, bold | canvas (0.90, 0.07, 250), Brand C 0.18 at L 0.55, wide L range between surfaces. High dominance is the point |
|
|
27
|
+
| Serene, tranquil | cool canvas (0.95, 0.03, 200), nothing above C 0.08, analogous 160 to 240 |
|
|
28
|
+
| Tender, gentle, romantic | blush canvas (0.95, 0.03, 20), rose Brand (0.70, 0.08, 10), sage Accent (0.68, 0.06, 150); narrow L range |
|
|
29
|
+
| Cozy, comforting | amber-cream canvas (0.92, 0.05, 75), rust Brand (0.55, 0.12, 40), neutrals at H 60; nothing cool on screen |
|
|
30
|
+
| Wistful, nostalgic, vintage, faded | faded canvas (0.92, 0.03, 70), every chromatic base color capped at C 0.10, hues warm and close. The feeling is chroma withheld, not darkness |
|
|
31
|
+
| Earthy, grounded, natural | canvas (0.90, 0.05, 90) at commitment level 2, hues 30 to 140 at C 0.06 to 0.14, neutrals H 60 to 80; no magenta, no cyan, nothing over C 0.16 |
|
|
32
|
+
| Clinical, sterile, precise | near-white canvas at C 0.01, the one request an untinted ground suits; one cool Brand 200 to 260 at C 0.10; statuses carry the only other color |
|
|
33
|
+
| Contemplative, focused | canvas (0.94, 0.015, 250) or its dark twin (0.20, 0.02, 250), one cool Brand at C 0.10, almost no other hue |
|
|
34
|
+
| Urgent, alarming | ground held near-neutral so the alarm lands, red Brand (0.58, 0.22, 27) given real area, Warning and Danger on one shared L |
|
|
35
|
+
| Tense, anxious | an uncomfortable ground, (0.88, 0.04, 105) light or (0.22, 0.03, 280) dark, plus a near-complementary pair that vibrates with one side toned down |
|
|
36
|
+
| Defiant, rebellious, loud | near-black canvas (0.15, 0.01, 0), one acid hue (0.85, 0.20, 120), nothing else chromatic |
|
|
37
|
+
| Melancholy, moody, sad | dark; canvas (0.22, 0.03, 250), chromatic base colors C 0.06 to 0.10 at L 0.72 to 0.80, blue through violet, with Accent held at C 0.14 as the moment of color |
|
|
38
|
+
| Somber, grave, mournful | near-neutral dark canvas (0.18, 0.01, 260), one desaturated Brand, gradient off |
|
|
39
|
+
| Ominous, dramatic, haunted | dark canvas (0.15, 0.04, 300), one hot accent (0.75, 0.16, 30) used sparingly, canvasGradient on |
|
|
40
|
+
| Austere, severe, cold | monochrome; canvas at either L extreme at C 0.01 or below, one low-chroma Brand, muted statuses |
|
|
41
|
+
|
|
42
|
+
## Idioms, eras, and genres
|
|
43
|
+
|
|
44
|
+
| Anchor | Anchors (L, C, H) |
|
|
45
|
+
|---|---|
|
|
46
|
+
| Swiss, International | near-white canvas (0.97, 0.01, 0), or true black for the poster reading; one red Brand (0.55, 0.22, 27) as the only hue on screen; Neutral at C 0.005, untinted on purpose; monochromatic |
|
|
47
|
+
| Bauhaus | paper canvas (0.95, 0.02, 85) under primaries at full commitment: red (0.58, 0.21, 27), blue (0.48, 0.20, 264), yellow (0.86, 0.17, 90); triadic |
|
|
48
|
+
| Mid-century modern | canvas (0.90, 0.05, 75), mustard (0.75, 0.13, 85), teal (0.55, 0.10, 195), burnt orange (0.60, 0.15, 45), walnut neutrals H 60; nothing over C 0.16; compound |
|
|
49
|
+
| Art deco, opulent, luxurious | near-black canvas (0.20, 0.02, 280), gold (0.78, 0.13, 88), jade (0.60, 0.10, 165); dark, one metallic accent, everything else grey |
|
|
50
|
+
| Terminal, phosphor | canvas (0.16, 0.01, 150), phosphor green Brand (0.80, 0.16, 145), amber Accent (0.80, 0.13, 80); monochromatic, dark, gradient off |
|
|
51
|
+
| Cyberpunk, neon noir, futuristic | canvas (0.18, 0.04, 300), magenta Brand (0.78, 0.18, 330), cyan Accent (0.82, 0.12, 200); complementary, dark, canvasGradient on for the glow |
|
|
52
|
+
| Vaporwave | sunset canvas (0.88, 0.06, 330), pink (0.72, 0.16, 350), cyan (0.80, 0.11, 205), lilac Special; light, gradient on |
|
|
53
|
+
| Y2K, bubble | chrome canvas (0.96, 0.015, 240), electric blue Brand (0.62, 0.18, 255), lime Accent (0.85, 0.17, 130) |
|
|
54
|
+
| Blueprint | canvas (0.35, 0.07, 245), pale rules (0.90, 0.02, 240), one warm accent (0.75, 0.14, 60); dark |
|
|
55
|
+
| Scandinavian, hygge | chalk canvas (0.96, 0.012, 70), sage Brand (0.60, 0.06, 150), clay Accent (0.70, 0.08, 40); nothing above C 0.10; analogous |
|
|
56
|
+
| Japandi, wabi-sabi | unbleached paper canvas (0.93, 0.025, 80), ink Brand (0.35, 0.02, 250), one earth Accent (0.62, 0.09, 45); near-monochrome |
|
|
57
|
+
| Cottagecore, botanical | cream canvas (0.94, 0.04, 85), moss (0.55, 0.10, 135), dusty rose (0.70, 0.09, 15), butter (0.85, 0.11, 95); warm analogous |
|
|
58
|
+
| Editorial, magazine | paper canvas (0.97, 0.015, 85), ink neutrals, one strong Brand (0.50, 0.18, 20) carried by rules and pull quotes |
|
|
59
|
+
| Newsprint, broadsheet | grey-warm canvas (0.91, 0.02, 80), near-black ink, nothing chromatic above C 0.10 |
|
|
60
|
+
| Risograph, zine | paper canvas (0.94, 0.03, 80) with two flat spot inks, fluoro pink (0.68, 0.22, 5) and blue (0.52, 0.18, 260); complementary, no midtones between them |
|
|
61
|
+
| Corporate, professional, trustworthy | canvas (0.97, 0.012, 250), navy Brand (0.48, 0.12, 255), teal Accent (0.60, 0.09, 195), conventional statuses |
|
|
62
|
+
| Brutalist | pure canvas, (0.98, 0, 0) or (0.15, 0, 0), with Neutral at C 0, untinted because that is the point; one alarming Brand (0.58, 0.24, 27) |
|
|
63
|
+
| Memphis, postmodern | pastel canvas (0.95, 0.03, 60) carrying full-chroma primaries and a hot pink Special (0.70, 0.20, 350); tetradic or square, four hue families on purpose |
|
|
64
|
+
| Industrial, workshop, gritty | concrete canvas (0.88, 0.008, 250), or (0.22, 0.01, 250) dark, safety orange Brand (0.68, 0.18, 50), steel neutrals |
|
|
65
|
+
|
|
66
|
+
## Occasions
|
|
67
|
+
|
|
68
|
+
An occasion is a statement request. Default to canvas commitment level 2 or 3,
|
|
69
|
+
never cream, and put the named color on the ground rather than only on the
|
|
70
|
+
buttons.
|
|
71
|
+
|
|
72
|
+
| Anchor | Anchors (L, C, H) | Strongest form |
|
|
73
|
+
|---|---|---|
|
|
74
|
+
| 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. |
|
|
75
|
+
| 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. |
|
|
76
|
+
| St. Patrick's | green (0.51, 0.13, 152) | green Brand, gold Accent, white or beige neutrals. |
|
|
77
|
+
| Ocean | deep blue (0.35, 0.08, 237), aqua (0.78, 0.12, 214) | hues held to 180 to 240. |
|
|
78
|
+
| Sunset | hues 90 to 320 through red | L falls 0.85 to 0.40 across the sweep. |
|
|
79
|
+
| 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. |
|
|
80
|
+
| Spring | pastels L 0.85 to 0.95, C 0.04 to 0.10 | greens 130 to 150, pinks 0 to 20, mint canvas. |
|