@tenphi/glaze 0.17.0 → 0.19.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/dist/index.cjs +65 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +30 -6
- package/dist/index.d.mts +30 -6
- package/dist/index.mjs +63 -13
- package/dist/index.mjs.map +1 -1
- package/docs/api.md +35 -16
- package/docs/migration.md +5 -2
- package/docs/okhst.md +49 -0
- package/package.json +1 -1
package/docs/api.md
CHANGED
|
@@ -127,12 +127,12 @@ theme.tokens()
|
|
|
127
127
|
|
|
128
128
|
### `theme.tasty(options?)`
|
|
129
129
|
|
|
130
|
-
Tasty style-to-state bindings for the [Tasty style system](https://tasty.style/docs). Uses `#name` color token keys and state aliases (`'
|
|
130
|
+
Tasty style-to-state bindings for the [Tasty style system](https://tasty.style/docs). Uses `#name` color token keys and state aliases. By default the dark and high-contrast variants are keyed by media-query states (`'@media(prefers-color-scheme: dark)'`, `'@media(prefers-contrast: more)'`) so tokens work without registering custom states.
|
|
131
131
|
|
|
132
132
|
```ts
|
|
133
133
|
theme.tasty()
|
|
134
134
|
// → {
|
|
135
|
-
// '#surface': { '': 'okhsl(...)', '@dark': 'okhsl(...)' },
|
|
135
|
+
// '#surface': { '': 'okhsl(...)', '@media(prefers-color-scheme: dark)': 'okhsl(...)' },
|
|
136
136
|
// ...
|
|
137
137
|
// }
|
|
138
138
|
```
|
|
@@ -143,13 +143,13 @@ theme.tasty()
|
|
|
143
143
|
|---|---|---|
|
|
144
144
|
| `format` | `'okhsl'` | Output color format. `'okhsl'` and `'okhst'` are supported here (Tasty-only spaces). |
|
|
145
145
|
| `modes` | global config | Which scheme variants to include. |
|
|
146
|
-
| `states.dark` | `'@dark'` (or global config) | State alias for dark mode tokens. |
|
|
147
|
-
| `states.highContrast` | `'@
|
|
146
|
+
| `states.dark` | `'@media(prefers-color-scheme: dark)'` (or global config) | State alias for dark mode tokens. |
|
|
147
|
+
| `states.highContrast` | `'@media(prefers-contrast: more)'` (or global config) | State alias for high-contrast tokens. |
|
|
148
148
|
| `splitHue` | `false` | Emit hue as a separate custom property (`$name-hue` token + `var()` in `oklch` values). Requires `format: 'oklch'` and every color to be pastel. |
|
|
149
149
|
| `name` | `'theme'` | Base name for the theme-level hue var (`$theme-hue` / `--theme-hue`). Palette export auto-derives this from the theme name. |
|
|
150
150
|
| `prefix` | (palette only) | See [Palette](#palette). |
|
|
151
151
|
|
|
152
|
-
When both `dark` and `highContrast` modes are enabled, dark high-contrast variants are emitted under the combined key `<dark> & <highContrast>` (e.g. `'@dark & @
|
|
152
|
+
When both `dark` and `highContrast` modes are enabled, dark high-contrast variants are emitted under the combined key `<dark> & <highContrast>` (e.g. `'@media(prefers-color-scheme: dark) & @media(prefers-contrast: more)'`).
|
|
153
153
|
|
|
154
154
|
### `theme.json(options?)`
|
|
155
155
|
|
|
@@ -403,12 +403,29 @@ A bare number or preset means **WCAG**. Use `{ wcag }` / `{ apca }` to pick the
|
|
|
403
403
|
contrast: 4.5 // WCAG 4.5
|
|
404
404
|
contrast: 'AAA' // WCAG 7
|
|
405
405
|
contrast: { wcag: 6 } // WCAG 6
|
|
406
|
-
contrast: { wcag: [4.5, 7] } // WCAG 4.5 normal / 7 high-contrast
|
|
407
|
-
contrast: { apca: 60 } // APCA Lc 60
|
|
408
|
-
contrast: { apca: [45, 60] } // APCA Lc 45 normal / 60 high-contrast
|
|
409
|
-
contrast: { apca: 'content' } // APCA preset -> Lc 60
|
|
410
|
-
contrast: { apca: ['content', 'body'] } // Lc 60 normal / 75 high-contrast
|
|
411
|
-
```
|
|
406
|
+
contrast: { wcag: [4.5, 7] } // WCAG 4.5 normal / 7 high-contrast (explicit)
|
|
407
|
+
contrast: { apca: 60 } // APCA Lc 60 normal / 75 high-contrast (auto)
|
|
408
|
+
contrast: { apca: [45, 60] } // APCA Lc 45 normal / 60 high-contrast (explicit)
|
|
409
|
+
contrast: { apca: 'content' } // APCA preset -> Lc 60 normal / 75 high-contrast (auto)
|
|
410
|
+
contrast: { apca: ['content', 'body'] } // Lc 60 normal / 75 high-contrast (explicit)
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
**WCAG HC auto-promotion:** a bare WCAG preset (no `[normal, hc]` pair at either
|
|
414
|
+
the outer `contrast` or inner `wcag` level) is automatically promoted to its
|
|
415
|
+
spec-defined "Enhanced" successor in high-contrast mode — `AA` → `AAA` (4.5 → 7)
|
|
416
|
+
and `AA-large` → `AAA-large` (3 → 4.5), per WCAG SC 1.4.3 → 1.4.6. `AAA` and
|
|
417
|
+
`AAA-large` are already the top WCAG tier and are left unchanged; bare numeric
|
|
418
|
+
targets have no successor tier and are also left unchanged. An explicit HC value
|
|
419
|
+
via either pair overrides and skips the promotion.
|
|
420
|
+
|
|
421
|
+
**APCA Enhanced Level (HC auto-boost):** a bare APCA scalar (no `[normal, hc]`
|
|
422
|
+
pair at either the outer `contrast` or inner `apca` level) is automatically
|
|
423
|
+
boosted by **+15 Lc** in high-contrast mode, the APCA analog of WCAG's
|
|
424
|
+
AAA-over-AA step. On by default; an explicit HC value via either pair
|
|
425
|
+
overrides it and skips the boost. The enhanced target is clamped to 106 Lc.
|
|
426
|
+
For large/bold text (where APCA caps contrast at Lc 90 to avoid glare), pass
|
|
427
|
+
an explicit HC pair to hold that ceiling — see
|
|
428
|
+
[`docs/okhst.md`](okhst.md) §Enhanced Level.
|
|
412
429
|
|
|
413
430
|
APCA preset keywords (Bronze Simple Mode conformance levels, role-independent):
|
|
414
431
|
`'preferred'` (Lc 90), `'body'` (75), `'content'` (60, ~AA), `'large'` (45, ~3:1),
|
|
@@ -1276,8 +1293,8 @@ glaze.configure({
|
|
|
1276
1293
|
darkTone: [15, 95], // [lo, hi]; or { lo, hi, eps } / false to disable clamping
|
|
1277
1294
|
darkDesaturation: 0.1,
|
|
1278
1295
|
states: {
|
|
1279
|
-
dark: '@dark',
|
|
1280
|
-
highContrast: '@
|
|
1296
|
+
dark: '@media(prefers-color-scheme: dark)',
|
|
1297
|
+
highContrast: '@media(prefers-contrast: more)',
|
|
1281
1298
|
},
|
|
1282
1299
|
modes: {
|
|
1283
1300
|
dark: true,
|
|
@@ -1299,8 +1316,8 @@ A `ToneWindow` is `[lo, hi]` (OKHSL-lightness endpoints, reference eps — the c
|
|
|
1299
1316
|
| `lightTone` | `[10, 100]` | Light scheme tone window: `[lo, hi]`, `{ lo, hi, eps }`, or `false` to disable clamping. Bypassed in HC. |
|
|
1300
1317
|
| `darkTone` | `[15, 95]` | Dark scheme tone window: `[lo, hi]`, `{ lo, hi, eps }`, or `false` to disable clamping. Bypassed in HC. |
|
|
1301
1318
|
| `darkDesaturation` | `0.1` | Saturation reduction in dark scheme (0–1). |
|
|
1302
|
-
| `states.dark` | `'@dark'` | State alias for dark mode tokens (Tasty export). |
|
|
1303
|
-
| `states.highContrast` | `'@
|
|
1319
|
+
| `states.dark` | `'@media(prefers-color-scheme: dark)'` | State alias for dark mode tokens (Tasty export). Defaults to a media query so tokens react to the OS preference without registering custom states. |
|
|
1320
|
+
| `states.highContrast` | `'@media(prefers-contrast: more)'` | State alias for HC tokens (Tasty export). |
|
|
1304
1321
|
| `modes.dark` | `true` | Include dark variants in exports. |
|
|
1305
1322
|
| `modes.highContrast` | `false` | Include HC variants. |
|
|
1306
1323
|
| `shadowTuning` | `undefined` | Default tuning for all shadow colors. Per-color tuning merges field-by-field. |
|
|
@@ -1465,10 +1482,12 @@ import {
|
|
|
1465
1482
|
|---|---|
|
|
1466
1483
|
| `findToneForContrast(opts)` | Binary-search for the tone (0–1) that meets a contrast floor (WCAG or APCA) against a base color. Returns `{ tone, contrast, met, branch, flipped? }`. |
|
|
1467
1484
|
| `findValueForMixContrast(opts)` | Same, but searches for a mix `value` (0–1) that meets a contrast floor between a base and a target. |
|
|
1468
|
-
| `resolveContrastForMode(spec, isHC)` | Resolves a `ContrastSpec` to `{ metric: 'wcag' \| 'apca', target }` for the requested mode (picks the normal or HC entry of any pair). |
|
|
1485
|
+
| `resolveContrastForMode(spec, isHC, polarity?, outerExplicitHC?)` | Resolves a `ContrastSpec` to `{ metric: 'wcag' \| 'apca', target }` for the requested mode (picks the normal or HC entry of any pair). In HC, applies the metric's auto-enhancement unless `outerExplicitHC` is set or the inner metric pair carries an explicit HC value: APCA +15 Lc (clamped to 106); WCAG AA → AAA / AA-large → AAA-large (AAA-family and bare numbers unchanged). |
|
|
1469
1486
|
| `resolveMinContrast(value)` | Resolves a `MinContrast` (WCAG preset or number) to a numeric ratio. |
|
|
1470
1487
|
| `apcaContrast(yText, yBg)` | APCA Lc magnitude (0–106) for two relative luminances. |
|
|
1471
1488
|
|
|
1489
|
+
Exported constants: `APCA_PRESETS`, `APCA_HC_ENHANCEMENT` (`15`, the Enhanced Level delta), `APCA_MAX_LC` (`106`).
|
|
1490
|
+
|
|
1472
1491
|
`findToneForContrast` options:
|
|
1473
1492
|
|
|
1474
1493
|
| Option | Default | Description |
|
package/docs/migration.md
CHANGED
|
@@ -106,7 +106,7 @@ Glaze emits the same resolved colors in six shapes. Pick one based on your rende
|
|
|
106
106
|
|
|
107
107
|
| Method | Output shape | Use it for |
|
|
108
108
|
|---|---|---|
|
|
109
|
-
| `palette.tasty(options?)` | `{ '#name': { '': value, '@dark': value, '@
|
|
109
|
+
| `palette.tasty(options?)` | `{ '#name': { '': value, '@media(prefers-color-scheme: dark)': value, '@media(prefers-contrast: more)': value } }` | The [Tasty](https://tasty.style/docs) style system. Single object, state aliases keyed inside each token. |
|
|
110
110
|
| `palette.tokens(options?)` | `{ light: { name: value }, dark: { name: value }, ... }` | Most CSS-in-JS systems. Per-variant flat maps, easy to feed into a `:root { ... }` selector via your framework's globals. |
|
|
111
111
|
| `palette.css(options?)` | `{ light: '--name-color: rgb(...);', dark: '...', ... }` | Framework-free CSS / static stylesheets. Variant-grouped CSS custom property strings ready to wrap in `:root` and `prefers-color-scheme` queries. |
|
|
112
112
|
| `palette.json(options?)` | `{ themeName: { name: { light, dark, ... } } }` | Tooling, JSON pipelines. |
|
|
@@ -136,11 +136,14 @@ useGlobalStyles('body', PALETTE_TOKENS);
|
|
|
136
136
|
tastyStatic('body', PALETTE_TOKENS);
|
|
137
137
|
```
|
|
138
138
|
|
|
139
|
-
|
|
139
|
+
By default the dark / high-contrast variants are keyed by media-query states — `'@media(prefers-color-scheme: dark)'` and `'@media(prefers-contrast: more)'` — so the tokens react to the OS preference out of the box, with no extra Tasty setup.
|
|
140
|
+
|
|
141
|
+
If you'd rather drive the schemes from custom aliases (e.g. a manual toggle that also falls back to the OS preference), set your own [`glaze.configure({ states })`](api.md#configuration) and register what those states *mean*:
|
|
140
142
|
|
|
141
143
|
```ts
|
|
142
144
|
import { setGlobalPredefinedStates } from '@tenphi/tasty';
|
|
143
145
|
|
|
146
|
+
// glaze.configure({ states: { dark: '@dark', highContrast: '@hc' } });
|
|
144
147
|
setGlobalPredefinedStates({
|
|
145
148
|
'@dark':
|
|
146
149
|
'@root(schema=dark) | (!@root(schema) & @media(prefers-color-scheme: dark))',
|
package/docs/okhst.md
CHANGED
|
@@ -239,6 +239,55 @@ contrast: { apca: 'content' } // Lc 60
|
|
|
239
239
|
contrast: { apca: ['content', 'body'] } // HC pair: 60 normal, 75 high-contrast
|
|
240
240
|
```
|
|
241
241
|
|
|
242
|
+
#### Enhanced Level (high-contrast auto-boost)
|
|
243
|
+
|
|
244
|
+
When an APCA target is given as a **bare scalar** (no `[normal, hc]` pair at
|
|
245
|
+
either the outer `contrast` level or the inner `apca` level), Glaze
|
|
246
|
+
automatically applies the APCA-W3 "Enhanced Level" delta — **+15 Lc** — in
|
|
247
|
+
high-contrast mode, analogous to WCAG's AAA-over-AA step. This is on by
|
|
248
|
+
default; provide an explicit HC value via either pair to override it.
|
|
249
|
+
|
|
250
|
+
```ts
|
|
251
|
+
contrast: { apca: 60 } // Lc 60 normal, Lc 75 high-contrast (auto)
|
|
252
|
+
contrast: { apca: 'content' } // Lc 60 normal, Lc 75 high-contrast (auto)
|
|
253
|
+
contrast: { apca: [60, 90] } // Lc 60 normal, Lc 90 high-contrast (explicit)
|
|
254
|
+
contrast: [{ apca: 60 }, { apca: 90 }] // outer pair: explicit HC, no boost
|
|
255
|
+
contrast: { apca: 'preferred' } // Lc 90 normal, Lc 105 high-contrast (auto)
|
|
256
|
+
contrast: { apca: 100 } // Lc 100 normal, Lc 106 high-contrast (clamped)
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
The enhanced target is clamped to `APCA_MAX_LC` (106).
|
|
260
|
+
|
|
261
|
+
> **Large-text glare caveat.** APCA-W3 also defines Lc 90 as a *maximum* for
|
|
262
|
+
> very large/bold text (>36px bold) and large areas of color, to prevent
|
|
263
|
+
> excessive glare. The +15 HC boost can therefore push a high baseline (e.g.
|
|
264
|
+
> `preferred` Lc 90 → 105) past that glare ceiling. This is intentional for
|
|
265
|
+
> small/standard text in HC (low-vision readability trumps glare, and small
|
|
266
|
+
> fonts have no APCA maximum), but if your HC tokens serve large/bold text,
|
|
267
|
+
> pass an explicit HC pair (`{ apca: [90, 90] }`) to hold the glare ceiling.
|
|
268
|
+
> Glaze does not model font size, so it can't enforce the large-text cap
|
|
269
|
+
> automatically.
|
|
270
|
+
|
|
271
|
+
#### WCAG HC auto-promotion
|
|
272
|
+
|
|
273
|
+
A bare WCAG preset (no `[normal, hc]` pair at either the outer `contrast` or
|
|
274
|
+
inner `wcag` level) is automatically promoted to its spec-defined "Enhanced"
|
|
275
|
+
successor in high-contrast mode — WCAG SC 1.4.3 (Minimum) → SC 1.4.6
|
|
276
|
+
(Enhanced), the direct analog of APCA's Enhanced Level:
|
|
277
|
+
|
|
278
|
+
```ts
|
|
279
|
+
contrast: 'AA' // 4.5 normal, 7 high-contrast (auto -> AAA)
|
|
280
|
+
contrast: 'AA-large' // 3 normal, 4.5 high-contrast (auto -> AAA-large)
|
|
281
|
+
contrast: 'AAA' // 7 both modes (top tier, unchanged)
|
|
282
|
+
contrast: 'AAA-large' // 4.5 both modes (top tier, unchanged)
|
|
283
|
+
contrast: 5.5 // 5.5 both modes (bare number, no successor tier)
|
|
284
|
+
contrast: { wcag: ['AA', 'AA'] } // 4.5 both modes (explicit HC, no promotion)
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
`AAA` and `AAA-large` are already the top WCAG tier and are left unchanged; bare
|
|
288
|
+
numeric targets have no defined successor tier and are also left unchanged. An
|
|
289
|
+
explicit HC value via either pair overrides and skips the promotion.
|
|
290
|
+
|
|
242
291
|
## Verification (APCA / WCAG drift)
|
|
243
292
|
|
|
244
293
|
Because chromatic swatches inherit gray's tone-derived lightness but drift in
|
package/package.json
CHANGED