@tenphi/glaze 0.0.0-snapshot.8f16949 → 0.0.0-snapshot.94c4efb

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 CHANGED
@@ -5,7 +5,7 @@
5
5
  <h1 align="center">Glaze</h1>
6
6
 
7
7
  <p align="center">
8
- OKHST-based color theme generator with WCAG contrast solving
8
+ OKHST-based color theme generator with WCAG and APCA contrast solving
9
9
  </p>
10
10
 
11
11
  <p align="center">
@@ -16,23 +16,31 @@
16
16
 
17
17
  ---
18
18
 
19
- Glaze generates robust **light**, **dark**, and **high-contrast** color schemes from a single hue/saturation seed. WCAG contrast is preserved via explicit dependency declarations — no hidden role math, no magic multipliers.
19
+ Glaze generates **light**, **dark**, and **high-contrast** color schemes from a
20
+ single hue/saturation seed. Relationships stay explicit: colors either define
21
+ an absolute tone or depend on a named base through a tone delta and an optional
22
+ contrast floor.
20
23
 
21
24
  ## Features
22
25
 
23
- - **OKHST color space** — OKHSL with a contrast-uniform **tone** axis (equal tone steps give equal contrast). See [`docs/okhst.md`](docs/okhst.md).
26
+ - **OKHST color space** — OKHSL with a contrast-shaped **tone** axis. Equal
27
+ steps give equal WCAG contrast for neutrals and a useful approximation for
28
+ chromatic colors. See [OKHST in Glaze](docs/okhst.md) and the
29
+ [full OKHST specification](https://github.com/tenphi/okhst).
24
30
  - **WCAG 2 + APCA contrast solving** — automatic tone adjustment to meet a WCAG ratio or APCA Lc floor
25
31
  - **Unified dark mode** — one tone space for light, dark, and high-contrast; dark is a single `100 − t` inversion, no fitted curve
26
32
  - **Mix colors** — blend two colors with OKHSL or sRGB interpolation, opaque or transparent, with optional contrast solving
27
33
  - **Shadow colors** — OKHSL-native shadow computation with automatic alpha, fg/bg tinting, and per-scheme adaptation
28
34
  - **Light + Dark + High-Contrast** — all schemes from one definition
35
+ - **Manual contrast level** — swap the high-contrast tier for a `0–100` slider; `0` is your normal palette, `100` the high-contrast one, and every level in between is solved, not approximated
29
36
  - **Per-color hue override** — absolute or relative hue shifts within a theme
30
- - **Multi-format output** — `okhsl`, `rgb`, `hsl`, `oklch` with modern CSS space syntax
37
+ - **Multi-format output** — native `rgb`, `hsl`, and `oklch`, plus
38
+ [Tasty](https://tasty.style)-compatible `okhsl` and `okhst`
31
39
  - **CSS custom properties export** — ready-to-use `--var: value;` declarations per scheme
32
40
  - **W3C DTCG export** — spec-conformant `.tokens.json` (2025.10) for Figma, Tokens Studio, Style Dictionary, and every DTCG tool
33
41
  - **W3C DTCG Resolver-Module export** — opt-in single-document `dtcgResolver()` (sets + a `scheme` modifier with a context per variant) for resolver tools such as Dispersa
34
42
  - **Tailwind CSS v4 export** — `@theme` block + dark / high-contrast overrides
35
- - **Import/Export** — serialize and restore theme configurations
43
+ - **Import/Export** — serialize and restore themes, color tokens, and entire palettes as JSON
36
44
  - **Create from hex/RGB** — start from an existing brand color
37
45
  - **Zero dependencies** — pure math, runs anywhere (Node.js, browser, edge)
38
46
  - **Tree-shakeable ESM + CJS** — dual-format package
@@ -57,43 +65,90 @@ yarn add @tenphi/glaze
57
65
  ```ts
58
66
  import { glaze } from '@tenphi/glaze';
59
67
 
60
- const primary = glaze(280, 80);
61
-
62
- primary.colors({
63
- surface: { tone: 97, saturation: 0.75 },
64
- text: { base: 'surface', tone: '-52', contrast: 'AAA' },
65
- border: { base: 'surface', tone: ['-7', '-20'], contrast: 'AA-large' },
66
- 'accent-fill': { tone: 52, mode: 'fixed' },
67
- 'accent-text': { base: 'accent-fill', tone: 'max', mode: 'fixed' },
68
- 'shadow-md': { type: 'shadow', bg: 'surface', fg: 'text', intensity: 10 },
68
+ glaze.configure({
69
+ modes: { dark: true, highContrast: true },
69
70
  });
70
71
 
71
- const danger = primary.extend({ hue: 23 });
72
- const success = primary.extend({ hue: 157 });
72
+ const defaultTheme = glaze(280, 80);
73
+
74
+ defaultTheme.colors({
75
+ surface: { tone: 97, saturation: 0.15 },
76
+ 'surface-text': {
77
+ base: 'surface',
78
+ tone: '-1',
79
+ contrast: { apca: ['content', 'body'] },
80
+ },
81
+ border: {
82
+ base: 'surface',
83
+ tone: ['-8', '-16'],
84
+ inherit: false,
85
+ },
86
+ 'accent-surface': { tone: 52, mode: 'fixed' },
87
+ 'accent-surface-text': {
88
+ base: 'accent-surface',
89
+ tone: '+1',
90
+ contrast: 'AA',
91
+ mode: 'fixed',
92
+ },
93
+ });
73
94
 
74
- const palette = glaze.palette(
75
- { primary, danger, success },
76
- { primary: 'primary' },
77
- );
95
+ const dangerTheme = defaultTheme.extend({ hue: 23 });
96
+ const palette = glaze.palette({ default: defaultTheme, danger: dangerTheme });
78
97
 
79
- const tokens = palette.tokens();
80
- // → { light: { 'primary-surface': 'okhsl(...)', 'surface': 'okhsl(...)', ... },
81
- // dark: { 'primary-surface': 'okhsl(...)', 'surface': 'okhsl(...)', ... } }
98
+ const tokens = palette.tokens({
99
+ prefix: { default: '', danger: 'danger-' },
100
+ });
101
+ // → {
102
+ // light: { surface: 'oklch(...)', 'danger-surface': 'oklch(...)', ... },
103
+ // dark: { surface: 'oklch(...)', 'danger-surface': 'oklch(...)', ... },
104
+ // lightContrast: { ... },
105
+ // darkContrast: { ... },
106
+ // }
82
107
  ```
83
108
 
84
109
  ## Concepts at a glance
85
110
 
86
- 1. **Theme = one hue/saturation seed.** Status themes are siblings created via `extend()` — they inherit every color definition and only swap the seed.
87
- 2. **Every color is explicit.** A color is either a *root* (absolute `tone`, or `'max'`/`'min'` for an extreme) or *dependent* (`base` + relative offset and/or `contrast`). No implicit roles.
88
- 3. **Tone is contrast-uniform.** `tone` (0–100) replaces OKHSL lightness: equal tone steps give equal WCAG contrast, so ramps are even by construction. See [`docs/okhst.md`](docs/okhst.md).
89
- 4. **`contrast` is a floor, not a target.** A bare number/preset is WCAG; `{ wcag }` / `{ apca }` selects the metric. The solver only shifts a color's tone when the requested position fails the requested floor.
90
- 5. **Light, dark, and high-contrast come from one definition.** `mode` (`auto` / `fixed` / `static`) picks how each color adapts; `tone` / `contrast` / `intensity` / `value` accept an optional `[normal, hc]` pair for explicit high-contrast tuning.
111
+ 1. **A theme has one hue/saturation seed.** Create status themes with
112
+ `extend()` so they inherit the same relationships while changing hue.
113
+ 2. **A color is a root or a dependency.** Roots use an absolute `tone` or
114
+ `'max'`/`'min'`. Dependent colors name a `base` and may use a signed
115
+ **tone delta** such as `'-8'` plus a `contrast` floor.
116
+ 3. **Tone is an authoring axis, not a contrast guarantee.** Equal tone deltas
117
+ are exact WCAG steps for neutrals. Chromatic colors can drift in rendered
118
+ luminance, so Glaze measures contrast floors against the resolved colors.
119
+ 4. **`contrast` is a floor.** A bare number or preset means WCAG;
120
+ `{ wcag }` and `{ apca }` select the metric explicitly. The solver preserves
121
+ the requested tone whenever it already passes.
122
+ 5. **Each color chooses its dark adaptation.** `mode: 'auto'` uses dark tone
123
+ inversion (`100 - t`), `fixed` keeps the authored side of the tone scale,
124
+ and `static` skips scheme adaptation.
125
+ 6. **Tone windows bound ordinary schemes.** `lightTone` and `darkTone`
126
+ configure the light/dark render ranges. High-contrast variants use the full
127
+ range. Values that accept `[normal, highContrast]` pairs can tighten
128
+ deliberately in HC.
129
+
130
+ In Glaze, a **scheme variant** is one of `light`, `dark`, `lightContrast`, or
131
+ `darkContrast`. Export `modes` choose which variants are included; [Tasty](https://tasty.style)
132
+ `states` choose how those variants are activated in an application.
133
+
134
+ ## Choosing an output
135
+
136
+ - `tasty()` returns [Tasty](https://tasty.style) `#token` bindings, including its custom `okhsl()` or
137
+ `okhst()` serialization.
138
+ - `tokens()` and `json()` return JavaScript data and default to native
139
+ `oklch()` values.
140
+ - `css()` returns custom-property declarations.
141
+ - `dtcg()` / `dtcgResolver()` target design-token tooling.
142
+ - `tailwind()` emits a Tailwind CSS v4 theme.
91
143
 
92
144
  ## Documentation
93
145
 
94
- - [`docs/api.md`](docs/api.md) — full API reference (every method, every option).
95
- - [`docs/methodology.md`](docs/methodology.md) — palette design methodology for building from scratch.
96
- - [`docs/migration.md`](docs/migration.md) — wiring tokens into your app and migrating off a legacy color system.
146
+ - Start with [the methodology](docs/methodology.md) to design a palette.
147
+ - Use [migration and integration](docs/migration.md) to wire it into an
148
+ application or replace an existing color system.
149
+ - Keep the [API reference](docs/api.md) nearby for every method and option.
150
+ - Read [OKHST in Glaze](docs/okhst.md) for the product-level color model, or
151
+ the [full OKHST specification](https://github.com/tenphi/okhst) for its math.
97
152
  - [`AGENTS.md`](AGENTS.md) — source-tree orientation for contributors.
98
153
 
99
154
  ## License