okchroma 0.1.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/LICENSE +21 -0
- package/README.md +135 -0
- package/dist-lib/index.cjs +3924 -0
- package/dist-lib/index.mjs +3901 -0
- package/dist-lib/types/engine/alphaPapers.d.ts +14 -0
- package/dist-lib/types/engine/archetypes.d.ts +13 -0
- package/dist-lib/types/engine/collision.d.ts +43 -0
- package/dist-lib/types/engine/colorEngine.d.ts +109 -0
- package/dist-lib/types/engine/colorMath.d.ts +181 -0
- package/dist-lib/types/engine/constraints.d.ts +18 -0
- package/dist-lib/types/engine/cssRender.d.ts +32 -0
- package/dist-lib/types/engine/darkChromaCurve.d.ts +2 -0
- package/dist-lib/types/engine/figmaRender.d.ts +34 -0
- package/dist-lib/types/engine/neutralCurve.d.ts +5 -0
- package/dist-lib/types/engine/p2.d.ts +12 -0
- package/dist-lib/types/engine/perceptualL.d.ts +11 -0
- package/dist-lib/types/engine/requirements/dtcg.d.ts +44 -0
- package/dist-lib/types/engine/requirements/producers.d.ts +160 -0
- package/dist-lib/types/engine/requirements/profiles.d.ts +7 -0
- package/dist-lib/types/engine/requirements/resolve.d.ts +46 -0
- package/dist-lib/types/engine/requirements/spec.d.ts +65 -0
- package/dist-lib/types/engine/resolve.d.ts +129 -0
- package/dist-lib/types/engine/signalShift.d.ts +8 -0
- package/dist-lib/types/engine/signals.d.ts +19 -0
- package/dist-lib/types/engine/stopTable.d.ts +76 -0
- package/dist-lib/types/engine/tokenDescriptions.d.ts +18 -0
- package/dist-lib/types/engine/tokenNames.d.ts +21 -0
- package/dist-lib/types/index.d.ts +11 -0
- package/package.json +68 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 OKChroma contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# OKChroma
|
|
2
|
+
|
|
3
|
+
**A color-system engine.** Give it one (or two) brand color(s) and it generates a complete,
|
|
4
|
+
accessible, theme-ready color system around it.
|
|
5
|
+
|
|
6
|
+
Each color family is a light and dark ramp built from pre-reserved roles — 2 papers,
|
|
7
|
+
5 washes, 2 highlights, and 2 inks — plus a solid CTA resting/hover pair and their
|
|
8
|
+
on-text colors, for each brand hex inputted. Alongside the brand color(s), it generates neutral, info-color, and red/yellow/green signal color scales. The inputted hex color(s) is/are preserved in identity swatches for logos or other brand identity moments.
|
|
9
|
+
|
|
10
|
+
The point is **white-label predictability**: every ramps's stops land at the same
|
|
11
|
+
perceived lightness and play the same role, so you map your design tokens to step
|
|
12
|
+
**numbers** once and they hold for any color scale. Contrast is built into the math, not
|
|
13
|
+
bolted on after: the system solves against **WCAG** ratios (every text color guaranteed
|
|
14
|
+
to pass), with **APCA** as an added legibility floor on CTA text (Lc 65 clearance on top
|
|
15
|
+
of the 4.5:1 requirement).
|
|
16
|
+
|
|
17
|
+
Output comes in two interchangeable forms carrying the same values:
|
|
18
|
+
|
|
19
|
+
- **CSS custom properties** — per-brand CSS generated live (`brandCss`) + the static
|
|
20
|
+
`dist/signals.css`, via the semantic layer `tokens/semantic.css`.
|
|
21
|
+
- **Figma variables** — written into a Figma file by the bundled plugin.
|
|
22
|
+
|
|
23
|
+
The live demo and the Figma plugin are previews/front-ends; the engine and its output are
|
|
24
|
+
the product.
|
|
25
|
+
|
|
26
|
+
> The "reserved role per step" model is a conceptual nod to
|
|
27
|
+
> [Radix Colors](https://www.radix-ui.com/colors/docs/palette-composition/understanding-the-scale).
|
|
28
|
+
> It is **not** a dependency and does not affect the math — all color computation is original.
|
|
29
|
+
|
|
30
|
+
## Quick start
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm install
|
|
34
|
+
npm run demo:build # generate token CSS + bundle the demo
|
|
35
|
+
npx serve . # then open http://localhost:3000/demo/index.html
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Live editing: `npm run dev` (watch mode). Build the Figma plugin: `npm run plugin:build`,
|
|
39
|
+
then import `plugin/manifest.json` in Figma.
|
|
40
|
+
|
|
41
|
+
## Use as an npm package
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npm install okchroma
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
import { resolveTheme, brandCss, signalsCss } from 'okchroma'
|
|
49
|
+
|
|
50
|
+
const t = resolveTheme({ primaryHex: '#E93D82', name: 'Acme' })
|
|
51
|
+
const css = brandCss('acme', 'Acme', t.themed) + '\n' + signalsCss()
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`resolveTheme` solves the full system for a seed (primary, optional secondary, neutral
|
|
55
|
+
source, signal policy). `brandCss` emits the solved light and dark values as CSS custom
|
|
56
|
+
properties scoped to `[data-brand="acme"]`, with dark values under
|
|
57
|
+
`[data-brand="acme"][data-theme="dark"]`; the per-brand neutral is included in the same
|
|
58
|
+
block. Variables are named `--brand-<token>`, `--neutral-<token>`, and
|
|
59
|
+
`--<signal>-<token>`. Inject the string into a `<style>` tag at runtime or write it to a
|
|
60
|
+
file at build time; `signalsCss()` is brand-independent and emitted once.
|
|
61
|
+
|
|
62
|
+
The same resolved theme feeds the other emitters: `themeToFigma` returns the Figma
|
|
63
|
+
variable payload, and `emitDtcgRamp` returns DTCG JSON carrying the live requirement in
|
|
64
|
+
`$extensions`. ESM and CJS builds ship with TypeScript declarations. The package bundles
|
|
65
|
+
its one runtime dependency (helmlab), so installing it adds nothing transitive.
|
|
66
|
+
|
|
67
|
+
## How it works (30 seconds)
|
|
68
|
+
|
|
69
|
+
Every token is a **requirement the engine solves, not a frozen value**. A pure-data
|
|
70
|
+
declaration (`src/engine/requirements/spec.ts`) states each stop's producer (perceptual
|
|
71
|
+
placement, warm drift, chroma ladder) and its requirements (contrast floors, seam
|
|
72
|
+
separations, on-text rules); a resolver executes it per seed — **produce → require →
|
|
73
|
+
refine**. `resolveBrand(hex)` runs that engine, applies **policy** (status-color
|
|
74
|
+
collisions, signal shifts), and an **emitter** (`cssRender` / `figmaRender`) maps the
|
|
75
|
+
resolved stops onto named tokens and picks light vs dark. The declaration also
|
|
76
|
+
round-trips to DTCG tokens (`$value` fallback + the live requirement in `$extensions`).
|
|
77
|
+
|
|
78
|
+
- **Engine:** `src/engine/*` — pure TypeScript with one runtime dependency (helmlab,
|
|
79
|
+
the P2 adjacency metric), bundled into the npm package at build time.
|
|
80
|
+
- **Entry points:** `resolveBrand` (`src/engine/resolve.ts`) and `generateScale`
|
|
81
|
+
(`src/engine/colorEngine.ts`, an adapter over the resolver — same signature as always).
|
|
82
|
+
- **Build:** `src/build.ts` writes the one static output, `dist/signals.css`. There is no
|
|
83
|
+
brand roster: per-brand CSS is generated live by whichever caller resolves a hex (the
|
|
84
|
+
demo's hex input, a plugin's form field).
|
|
85
|
+
|
|
86
|
+
## The Figma plugin
|
|
87
|
+
|
|
88
|
+
The bundled plugin runs the same engine inside Figma and writes the resolved system into
|
|
89
|
+
your file as variables: **theme** + **mode** collections whose semantic tokens alias onto
|
|
90
|
+
shared primitives — per-brand ramps under `brand/<name>`, with neutrals and signals
|
|
91
|
+
deduplicated across brands, light + dark values on every token.
|
|
92
|
+
|
|
93
|
+
**Install** — from source:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
npm install && npm run plugin:build
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
then Figma → Plugins → Development → **Import plugin from manifest** →
|
|
100
|
+
`plugin/manifest.json`.
|
|
101
|
+
|
|
102
|
+
> The hosted download for **this** plugin is **withdrawn** as of 2026-07-29. The scale
|
|
103
|
+
> changed shape in that round — `highlight-9` and `on-highlight` were removed and the ink
|
|
104
|
+
> stops renumbered — and this plugin does not yet carry the rename table that migrates an
|
|
105
|
+
> existing Figma file across it, so updating an installed copy would orphan its variable
|
|
106
|
+
> bindings. Building from source is unaffected: a fresh file gets the new shape correctly.
|
|
107
|
+
>
|
|
108
|
+
> The **extended collections** plugin (Figma Enterprise) does carry the migration and is
|
|
109
|
+
> published as normal — **[install it here](https://egerrity.github.io/okchroma/install.html)**.
|
|
110
|
+
|
|
111
|
+
**Use** — name the brand, pick a primary, and Apply. Optional before applying:
|
|
112
|
+
|
|
113
|
+
- **Secondary color** — "+ Add secondary" starts on *From primary* (a pastel derived from
|
|
114
|
+
your primary); type any hex for a custom secondary in **Tint / Pastel / Outline / Exact**
|
|
115
|
+
style.
|
|
116
|
+
- **Neutral color** — *Default* (a touch of primary hue), *Medium* (slightly more tint), *Intense*, or *True grey*.
|
|
117
|
+
- **Contrast standard** — **APCA** (default) or **WCAG**. One profile per collection pair:
|
|
118
|
+
applying the other profile to an existing file forks a clearly-labeled second pair
|
|
119
|
+
(`theme-wcag`/`mode-wcag`) instead of ever mixing values.
|
|
120
|
+
|
|
121
|
+
Re-applying the same brand name updates it in place (after a confirm); a new name adds a
|
|
122
|
+
brand to the same collections — two applies with two brand colors is a multi-brand system
|
|
123
|
+
on shared foundations.
|
|
124
|
+
|
|
125
|
+
## Documentation
|
|
126
|
+
|
|
127
|
+
Full system documentation — overview, architecture (data flow + design decisions),
|
|
128
|
+
dependencies, setup — is in **[docs/architecture.md](docs/architecture.md)**.
|
|
129
|
+
The scale model and its per-stop targets are in **[docs/scale.md](docs/scale.md)**.
|
|
130
|
+
The requirement-token schema — the DTCG token format, field by field, with real
|
|
131
|
+
emitted examples — is in **[docs/schema.md](docs/schema.md)**.
|
|
132
|
+
|
|
133
|
+
## License
|
|
134
|
+
|
|
135
|
+
MIT
|