okchroma 0.6.1 → 0.7.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/README.md +79 -17
- package/dist-lib/index.cjs +324 -558
- package/dist-lib/index.mjs +324 -558
- package/dist-lib/types/engine/cssRender.d.ts +0 -37
- package/dist-lib/types/engine/dtcgRender.d.ts +39 -0
- package/dist-lib/types/engine/figmaRender.d.ts +1 -5
- package/dist-lib/types/engine/tokenDescriptions.d.ts +20 -0
- package/dist-lib/types/engine/tokenNames.d.ts +13 -30
- package/dist-lib/types/engine/tokensRender.d.ts +2 -4
- package/dist-lib/types/index.d.ts +6 -7
- package/package.json +6 -5
- package/tokens/semantic.css +0 -202
package/README.md
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
# OKChroma
|
|
2
2
|
|
|
3
|
-
**A color-system engine.** Give it one brand hex, or two, and it resolves a complete
|
|
4
|
-
light and dark
|
|
5
|
-
then emits it as CSS custom properties
|
|
3
|
+
**A color-system engine.** Give it one brand hex, or two, and it resolves a complete set
|
|
4
|
+
of light and dark color primitives whose contrast requirements are solved during
|
|
5
|
+
generation, then emits it as CSS custom properties, as DTCG documents, and as Figma
|
|
6
|
+
variables, every token spelled the same way in each.
|
|
6
7
|
|
|
7
8
|
Every family (neutral, brand, brand-alt, critical, warning, positive, info) carries the
|
|
8
9
|
same scale: 3 papers, 4 chalks, 1 highlighter, 1 pencil, 2 pens, plus the stamp (the
|
|
9
10
|
solid fill with its hover and pressed states, its edge, and its text). The neutral adds
|
|
10
|
-
the two poles.
|
|
11
|
-
mapped once and holds for any
|
|
11
|
+
the two poles. Two link trios and the two brand seeds complete the set. Light and dark
|
|
12
|
+
resolve together and ship on the same names, so a token is mapped once and holds for any
|
|
13
|
+
brand.
|
|
12
14
|
|
|
13
15
|
Contrast is built into the math, not checked afterwards: highlighter reads on every paper at
|
|
14
16
|
3:1 (the non-text bar), pencil at 4.5:1, pen at 4.5:1 on every paper and chalk in
|
|
@@ -16,6 +18,10 @@ both directions; the stamp's text passes 4.5:1 on its fill. APCA is used once, a
|
|
|
16
18
|
that nudges the stamp fill until its text reads at Lc 65. Each claim, its scope, and the audit that
|
|
17
19
|
proves it: [Guarantees](https://egerrity.github.io/okchroma/#/docs/guarantees).
|
|
18
20
|
|
|
21
|
+
The engine emits primitives only: values it calculates from the seed. Elevation planes,
|
|
22
|
+
shadows, opacity ladders and state layers are a design system's to author on top of these,
|
|
23
|
+
and [docs/agents.md](docs/agents.md) says which primitive each of those decisions reads.
|
|
24
|
+
|
|
19
25
|
> The reserved-role-per-stop model is a conceptual nod to
|
|
20
26
|
> [Radix Colors](https://www.radix-ui.com/colors/docs/palette-composition/understanding-the-scale).
|
|
21
27
|
> It is not a dependency and does not touch the math; the color computation is original.
|
|
@@ -27,22 +33,77 @@ npm install okchroma
|
|
|
27
33
|
```
|
|
28
34
|
|
|
29
35
|
ESM and CommonJS builds with TypeScript declarations; no runtime dependencies (the one
|
|
30
|
-
perceptual-distance library the engine uses is bundled in).
|
|
36
|
+
perceptual-distance library the engine uses is bundled in). Node 18 or later; no DOM.
|
|
31
37
|
|
|
32
38
|
```ts
|
|
33
|
-
import { resolveTheme, brandCss, signalsCss, neutralTintHue } from 'okchroma'
|
|
39
|
+
import { resolveTheme, brandCss, signalsCss, themeTokens, tokensToDtcg, neutralTintHue } from 'okchroma'
|
|
34
40
|
|
|
35
41
|
const theme = resolveTheme({ primaryHex: '#E93D82', name: 'acme', deriveSecondary: true })
|
|
36
42
|
const neutralH = neutralTintHue(theme.themed.scale.brandH)
|
|
43
|
+
|
|
44
|
+
// CSS custom properties: a light and a dark block per brand, the signal block once
|
|
37
45
|
const css = brandCss('acme', 'Acme', theme.themed, theme.secondary?.scale ?? null,
|
|
38
46
|
'', 'default', undefined, theme.secondary?.style, false, null, true, neutralH)
|
|
39
47
|
+ '\n' + signalsCss()
|
|
40
48
|
// put css in a stylesheet; set data-brand="acme" on the themed root,
|
|
41
49
|
// and data-theme="dark" on it for dark mode
|
|
50
|
+
|
|
51
|
+
// the same values as one object per mode, every var() resolved
|
|
52
|
+
const tokens = themeTokens({ slug: 'acme', brand: theme.themed, secondary: theme.secondary?.scale ?? null, secondaryStyle: theme.secondary?.style, neutralH })
|
|
53
|
+
|
|
54
|
+
// the DTCG documents: one per mode, every token with its description
|
|
55
|
+
const { light, dark } = tokensToDtcg(tokens)
|
|
42
56
|
```
|
|
43
57
|
|
|
44
|
-
The
|
|
45
|
-
[Install and API](https://egerrity.github.io/okchroma/#/docs/install).
|
|
58
|
+
The Figma tree comes from `themeToFigma`. Signatures, the full input, and an end-to-end
|
|
59
|
+
example: [Install and API](https://egerrity.github.io/okchroma/#/docs/install).
|
|
60
|
+
|
|
61
|
+
## What it emits
|
|
62
|
+
|
|
63
|
+
Every token has one path, and every output spells it: `brand/stamp/fill`,
|
|
64
|
+
`neutral/paper-0`, `link/default/enabled`, `absolute/brand`. Joined with hyphens it is the
|
|
65
|
+
CSS custom property (`--brand-stamp-fill`); joined with slashes it is the Figma variable
|
|
66
|
+
and the DTCG token path.
|
|
67
|
+
|
|
68
|
+
| Group | Tokens |
|
|
69
|
+
|---|---|
|
|
70
|
+
| `neutral` | `paper-0`, `paper-1`, `paper-3`, `paper-5`, `chalk-8`, `chalk-11`, `chalk-15`, `chalk-20`, `highlighter-26`, `pencil-47`, `pen-58`, `pen-70`, `pen-100`, and the stamp: `stamp/fill`, `stamp/fill-hover`, `stamp/fill-pressed`, `stamp/edge`, `stamp/on` |
|
|
71
|
+
| `brand`, `brand-alt`, `critical`, `warning`, `positive`, `info` | the same eleven stops and the same five stamp tokens |
|
|
72
|
+
| `link` | `default/enabled`, `default/hover`, `default/pressed` for text on the papers; `inverse/enabled`, `inverse/hover`, `inverse/pressed` for text on the pen ground |
|
|
73
|
+
| `absolute` | `brand`, `brand-alt`: the seeds as given, reference values |
|
|
74
|
+
|
|
75
|
+
What each name means, which stop to read for which job, and the rules for an agent
|
|
76
|
+
writing UI against these: [docs/agents.md](docs/agents.md). The scale and its declared
|
|
77
|
+
targets: [docs/scale.md](docs/scale.md).
|
|
78
|
+
|
|
79
|
+
**The stops.** The instrument word is the job, the number is 100 minus the light-mode
|
|
80
|
+
lightness target, and bigger is stronger. Papers are backgrounds; chalks are decorative
|
|
81
|
+
borders and illustration, never text; the highlighter is the non-text contrast stop (focus
|
|
82
|
+
rings, icons, large text, and the one stop to build translucent state layers on); the
|
|
83
|
+
pencil and the pens are text, and the pencil doubles as the emphasis fill.
|
|
84
|
+
|
|
85
|
+
**The stamp.** `stamp/fill` is the call-to-action fill, re-solved per family and theme;
|
|
86
|
+
`fill-hover` and `fill-pressed` are its states; `stamp/on` is the text over it, the pole
|
|
87
|
+
that passes (the pole at alpha on a quiet fill); `stamp/edge` is a stroke that resolves to
|
|
88
|
+
a visible offset only where the fill sits close to the page, else transparent, so a
|
|
89
|
+
component renders the border unconditionally and layout never shifts.
|
|
90
|
+
|
|
91
|
+
**The outputs.**
|
|
92
|
+
|
|
93
|
+
- CSS: `brandCss` writes `[data-brand="acme"]` and `[data-brand="acme"][data-theme="dark"]`
|
|
94
|
+
blocks, `signalsCss` the brand-independent signal block at `:root`. Values are sRGB
|
|
95
|
+
hexes (or `rgba()` where a token carries alpha); stops whose chroma exceeds sRGB get a
|
|
96
|
+
`color(display-p3 …)` override behind a browser gate. The repo's `npm run generate`
|
|
97
|
+
writes the signal block to `dist/signals.css`.
|
|
98
|
+
- The structured emit: `themeTokens` reads the CSS emission back into one object per
|
|
99
|
+
mode with every reference resolved, for consumers with no cascade.
|
|
100
|
+
- DTCG: `tokensToDtcg` returns one Design Tokens Format Module 2025.10 document per mode,
|
|
101
|
+
every token with `$type`, an sRGB `$value` whose components and hex are the same 8-bit
|
|
102
|
+
color (or an alias where the CSS writes a reference), and a `$description`. The two join
|
|
103
|
+
through a resolver document. The format: [docs/schema.md](docs/schema.md). The repo's
|
|
104
|
+
`npm run tokens:emit -- '#E93D82' acme` writes both files.
|
|
105
|
+
- Figma: `themeToFigma` returns a light and a dark group tree on the same paths; the
|
|
106
|
+
extended plugin writes it into a file.
|
|
46
107
|
|
|
47
108
|
## Run from source
|
|
48
109
|
|
|
@@ -54,13 +115,14 @@ npm run dev # watch mode
|
|
|
54
115
|
```
|
|
55
116
|
|
|
56
117
|
`npm run typecheck` runs the compiler; the audit gates (`npm run req:audit`,
|
|
57
|
-
`npm run audit:guarantee`, and the rest of `package.json`) each
|
|
58
|
-
fail on the worst case. What each proves:
|
|
118
|
+
`npm run audit:guarantee`, `npm run audit:dtcg`, and the rest of `package.json`) each
|
|
119
|
+
sweep agnostic seeds and fail on the worst case. What each proves:
|
|
59
120
|
[How it is verified](https://egerrity.github.io/okchroma/#/docs/guarantees/how-it-is-verified).
|
|
60
121
|
|
|
61
122
|
## Documentation
|
|
62
123
|
|
|
63
|
-
The docs site
|
|
124
|
+
The docs site renders the mechanisms with live values from the engine:
|
|
125
|
+
[egerrity.github.io/okchroma/#/docs](https://egerrity.github.io/okchroma/#/docs).
|
|
64
126
|
|
|
65
127
|
- [Overview](https://egerrity.github.io/okchroma/#/docs/overview): what goes in, what comes out, the token roster.
|
|
66
128
|
- [Output contract](https://egerrity.github.io/okchroma/#/docs/output): the naming grammar, families and prefixes, modes and selectors, a live CSS block and Figma tree.
|
|
@@ -68,12 +130,12 @@ The docs site is the source: [egerrity.github.io/okchroma/#/docs](https://egerri
|
|
|
68
130
|
- [How the theme is generated](https://egerrity.github.io/okchroma/#/docs/generation): the pipeline in execution order, with the constants and the code that runs each step.
|
|
69
131
|
- [Signals and companions](https://egerrity.github.io/okchroma/#/docs/signals) and the [Reference](https://egerrity.github.io/okchroma/#/docs/reference): glossary, constants, option types.
|
|
70
132
|
|
|
71
|
-
In the repo: [docs/
|
|
72
|
-
|
|
133
|
+
In the repo: [docs/agents.md](docs/agents.md) (the consumer contract: what every token
|
|
134
|
+
means and the rules for using it), [docs/schema.md](docs/schema.md) (the DTCG documents),
|
|
73
135
|
[docs/scale.md](docs/scale.md) (the scale and its declared targets),
|
|
74
|
-
[docs/
|
|
75
|
-
|
|
76
|
-
|
|
136
|
+
[docs/architecture.md](docs/architecture.md) (the maintainer's map: modules, pipeline
|
|
137
|
+
stages, data structures, the extended plugin's write path), and
|
|
138
|
+
[CHANGELOG.md](CHANGELOG.md).
|
|
77
139
|
|
|
78
140
|
## The Figma plugins
|
|
79
141
|
|