@tenphi/glaze 0.1.1 → 0.3.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 +165 -73
- package/dist/index.cjs +129 -43
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +45 -13
- package/dist/index.d.mts +45 -13
- package/dist/index.mjs +129 -43
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -23,7 +23,9 @@ Glaze generates robust **light**, **dark**, and **high-contrast** color schemes
|
|
|
23
23
|
- **OKHSL color space** — perceptually uniform hue and saturation
|
|
24
24
|
- **WCAG 2 contrast solving** — automatic lightness adjustment to meet AA/AAA targets
|
|
25
25
|
- **Light + Dark + High-Contrast** — all schemes from one definition
|
|
26
|
+
- **Per-color hue override** — absolute or relative hue shifts within a theme
|
|
26
27
|
- **Multi-format output** — `okhsl`, `rgb`, `hsl`, `oklch`
|
|
28
|
+
- **CSS custom properties export** — ready-to-use `--var: value;` declarations per scheme
|
|
27
29
|
- **Import/Export** — serialize and restore theme configurations
|
|
28
30
|
- **Create from hex/RGB** — start from an existing brand color
|
|
29
31
|
- **Zero dependencies** — pure math, runs anywhere (Node.js, browser, edge)
|
|
@@ -54,11 +56,11 @@ const primary = glaze(280, 80);
|
|
|
54
56
|
|
|
55
57
|
// Define colors with explicit lightness and contrast relationships
|
|
56
58
|
primary.colors({
|
|
57
|
-
surface:
|
|
58
|
-
text:
|
|
59
|
-
border:
|
|
60
|
-
'accent-fill': {
|
|
61
|
-
'accent-text': { base: 'accent-fill',
|
|
59
|
+
surface: { lightness: 97, saturation: 0.75 },
|
|
60
|
+
text: { base: 'surface', lightness: '-52', contrast: 'AAA' },
|
|
61
|
+
border: { base: 'surface', lightness: ['-7', '-20'], contrast: 'AA-large' },
|
|
62
|
+
'accent-fill': { lightness: 52, mode: 'fixed' },
|
|
63
|
+
'accent-text': { base: 'accent-fill', lightness: '+48', contrast: 'AA', mode: 'fixed' },
|
|
62
64
|
});
|
|
63
65
|
|
|
64
66
|
// Create status themes by rotating the hue
|
|
@@ -77,6 +79,8 @@ const tokens = palette.tokens({ prefix: true });
|
|
|
77
79
|
|
|
78
80
|
A single `glaze` theme is tied to one hue/saturation seed. Status colors (danger, success, warning) are derived via `extend`, which inherits all color definitions and replaces the seed.
|
|
79
81
|
|
|
82
|
+
Individual colors can override the hue via the `hue` prop (see [Per-Color Hue Override](#per-color-hue-override)), but the primary purpose of a theme is to scope colors with the same hue.
|
|
83
|
+
|
|
80
84
|
### Color Definitions
|
|
81
85
|
|
|
82
86
|
Every color is defined explicitly. No implicit roles — every value is stated.
|
|
@@ -85,48 +89,73 @@ Every color is defined explicitly. No implicit roles — every value is stated.
|
|
|
85
89
|
|
|
86
90
|
```ts
|
|
87
91
|
primary.colors({
|
|
88
|
-
surface: {
|
|
89
|
-
border: {
|
|
92
|
+
surface: { lightness: 97, saturation: 0.75 },
|
|
93
|
+
border: { lightness: 90, saturation: 0.20 },
|
|
90
94
|
});
|
|
91
95
|
```
|
|
92
96
|
|
|
93
|
-
- `
|
|
94
|
-
- `
|
|
97
|
+
- `lightness` — lightness in the light scheme (0–100)
|
|
98
|
+
- `saturation` — saturation factor applied to the seed saturation (0–1, default: `1`)
|
|
95
99
|
|
|
96
100
|
#### Dependent Colors (relative to base)
|
|
97
101
|
|
|
98
102
|
```ts
|
|
99
103
|
primary.colors({
|
|
100
|
-
surface: {
|
|
101
|
-
text: { base: 'surface',
|
|
104
|
+
surface: { lightness: 97, saturation: 0.75 },
|
|
105
|
+
text: { base: 'surface', lightness: '-52', contrast: 'AAA' },
|
|
102
106
|
});
|
|
103
107
|
```
|
|
104
108
|
|
|
105
109
|
- `base` — name of another color in the same theme
|
|
106
|
-
- `
|
|
107
|
-
- `
|
|
110
|
+
- `lightness` — position of this color (see [Lightness Values](#lightness-values))
|
|
111
|
+
- `contrast` — ensures the WCAG contrast ratio meets a target floor against the base
|
|
108
112
|
|
|
109
|
-
|
|
113
|
+
### Lightness Values
|
|
110
114
|
|
|
111
|
-
|
|
115
|
+
The `lightness` prop accepts two forms:
|
|
112
116
|
|
|
113
|
-
|
|
|
114
|
-
|
|
115
|
-
|
|
|
116
|
-
|
|
|
117
|
-
|
|
117
|
+
| Form | Example | Meaning |
|
|
118
|
+
|---|---|---|
|
|
119
|
+
| Number (absolute) | `lightness: 45` | Absolute lightness 0–100 |
|
|
120
|
+
| String (relative) | `lightness: '-52'` | Relative to base color's lightness |
|
|
121
|
+
|
|
122
|
+
**Absolute lightness** on a dependent color (with `base`) positions the color independently. In dark mode, it is dark-mapped on its own. The `contrast` WCAG solver acts as a safety net.
|
|
123
|
+
|
|
124
|
+
**Relative lightness** applies a signed delta to the base color's resolved lightness. In dark mode with `auto` adaptation, the sign flips automatically.
|
|
118
125
|
|
|
119
126
|
```ts
|
|
120
|
-
//
|
|
121
|
-
'text': { base: 'surface',
|
|
122
|
-
// → 97 + 52 = 149 > 100 → flips to 97 - 52 = 45 ✓
|
|
127
|
+
// Relative: 97 - 52 = 45 in light mode
|
|
128
|
+
'text': { base: 'surface', lightness: '-52' }
|
|
123
129
|
|
|
124
|
-
//
|
|
125
|
-
'
|
|
126
|
-
// → 52 + 48 = 100 → keeps as 100 ✓
|
|
130
|
+
// Absolute: lightness 45 in light mode, dark-mapped independently
|
|
131
|
+
'text': { base: 'surface', lightness: 45 }
|
|
127
132
|
```
|
|
128
133
|
|
|
129
|
-
|
|
134
|
+
A dependent color with `base` but no `lightness` inherits the base's lightness (equivalent to a delta of 0).
|
|
135
|
+
|
|
136
|
+
### Per-Color Hue Override
|
|
137
|
+
|
|
138
|
+
Individual colors can override the theme's hue. The `hue` prop accepts:
|
|
139
|
+
|
|
140
|
+
| Form | Example | Meaning |
|
|
141
|
+
|---|---|---|
|
|
142
|
+
| Number (absolute) | `hue: 120` | Absolute hue 0–360 |
|
|
143
|
+
| String (relative) | `hue: '+20'` | Relative to the **theme seed** hue |
|
|
144
|
+
|
|
145
|
+
**Important:** Relative hue is always relative to the **theme seed hue**, not to a base color's hue.
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
const theme = glaze(280, 80);
|
|
149
|
+
theme.colors({
|
|
150
|
+
surface: { lightness: 97 },
|
|
151
|
+
// Gradient end — slight hue shift from seed (280 + 20 = 300)
|
|
152
|
+
gradientEnd: { lightness: 90, hue: '+20' },
|
|
153
|
+
// Entirely different hue
|
|
154
|
+
warning: { lightness: 60, hue: 40 },
|
|
155
|
+
});
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### contrast (WCAG Floor)
|
|
130
159
|
|
|
131
160
|
Ensures the WCAG contrast ratio meets a target floor. Accepts a numeric ratio or a preset string:
|
|
132
161
|
|
|
@@ -141,26 +170,26 @@ type MinContrast = number | 'AA' | 'AAA' | 'AA-large' | 'AAA-large';
|
|
|
141
170
|
| `'AA-large'` | 3 |
|
|
142
171
|
| `'AAA-large'` | 4.5 |
|
|
143
172
|
|
|
144
|
-
You can also pass any numeric ratio directly (e.g., `
|
|
173
|
+
You can also pass any numeric ratio directly (e.g., `contrast: 4.5`, `contrast: 7`, `contrast: 11`).
|
|
145
174
|
|
|
146
|
-
The constraint is applied independently for each scheme. If the `
|
|
175
|
+
The constraint is applied independently for each scheme. If the `lightness` already satisfies the floor, it's kept. Otherwise, the solver adjusts lightness until the target is met.
|
|
147
176
|
|
|
148
177
|
### High-Contrast via Array Values
|
|
149
178
|
|
|
150
|
-
`
|
|
179
|
+
`lightness` and `contrast` accept a `[normal, high-contrast]` pair:
|
|
151
180
|
|
|
152
181
|
```ts
|
|
153
|
-
'border': { base: 'surface',
|
|
154
|
-
//
|
|
155
|
-
//
|
|
182
|
+
'border': { base: 'surface', lightness: ['-7', '-20'], contrast: 'AA-large' }
|
|
183
|
+
// ↑ ↑
|
|
184
|
+
// normal high-contrast
|
|
156
185
|
```
|
|
157
186
|
|
|
158
187
|
A single value applies to both modes. All control is local and explicit.
|
|
159
188
|
|
|
160
189
|
```ts
|
|
161
|
-
'text': { base: 'surface',
|
|
162
|
-
'border': { base: 'surface',
|
|
163
|
-
'muted': { base: 'surface',
|
|
190
|
+
'text': { base: 'surface', lightness: '-52', contrast: 'AAA' }
|
|
191
|
+
'border': { base: 'surface', lightness: ['-7', '-20'], contrast: 'AA-large' }
|
|
192
|
+
'muted': { base: 'surface', lightness: ['-35', '-50'], contrast: ['AA-large', 'AA'] }
|
|
164
193
|
```
|
|
165
194
|
|
|
166
195
|
## Theme Color Management
|
|
@@ -171,8 +200,8 @@ A single value applies to both modes. All control is local and explicit.
|
|
|
171
200
|
|
|
172
201
|
```ts
|
|
173
202
|
const theme = glaze(280, 80);
|
|
174
|
-
theme.colors({ surface: {
|
|
175
|
-
theme.colors({ text: {
|
|
203
|
+
theme.colors({ surface: { lightness: 97 } });
|
|
204
|
+
theme.colors({ text: { lightness: 30 } });
|
|
176
205
|
// Both 'surface' and 'text' are now defined
|
|
177
206
|
```
|
|
178
207
|
|
|
@@ -181,8 +210,8 @@ theme.colors({ text: { l: 30 } });
|
|
|
181
210
|
`.color(name)` returns the definition, `.color(name, def)` sets it:
|
|
182
211
|
|
|
183
212
|
```ts
|
|
184
|
-
theme.color('surface', {
|
|
185
|
-
const def = theme.color('surface');
|
|
213
|
+
theme.color('surface', { lightness: 97, saturation: 0.75 }); // set
|
|
214
|
+
const def = theme.color('surface'); // get → { lightness: 97, saturation: 0.75 }
|
|
186
215
|
```
|
|
187
216
|
|
|
188
217
|
### Removing Colors
|
|
@@ -214,7 +243,7 @@ Serialize a theme's configuration (hue, saturation, color definitions) to a plai
|
|
|
214
243
|
```ts
|
|
215
244
|
// Export
|
|
216
245
|
const snapshot = theme.export();
|
|
217
|
-
// → { hue: 280, saturation: 80, colors: { surface: {
|
|
246
|
+
// → { hue: 280, saturation: 80, colors: { surface: { lightness: 97, saturation: 0.75 }, ... } }
|
|
218
247
|
|
|
219
248
|
const jsonString = JSON.stringify(snapshot);
|
|
220
249
|
|
|
@@ -230,14 +259,14 @@ The export contains only the configuration — not resolved color values. Resolv
|
|
|
230
259
|
Create a single color token without a full theme:
|
|
231
260
|
|
|
232
261
|
```ts
|
|
233
|
-
const accent = glaze.color({ hue: 280, saturation: 80,
|
|
262
|
+
const accent = glaze.color({ hue: 280, saturation: 80, lightness: 52, mode: 'fixed' });
|
|
234
263
|
|
|
235
264
|
accent.resolve(); // → ResolvedColor with light/dark/lightContrast/darkContrast
|
|
236
265
|
accent.token(); // → { '': 'okhsl(...)', '@dark': 'okhsl(...)' }
|
|
237
266
|
accent.json(); // → { light: 'okhsl(...)', dark: 'okhsl(...)' }
|
|
238
267
|
```
|
|
239
268
|
|
|
240
|
-
Standalone colors are always root colors (no `base`/`contrast
|
|
269
|
+
Standalone colors are always root colors (no `base`/`contrast`).
|
|
241
270
|
|
|
242
271
|
## From Existing Colors
|
|
243
272
|
|
|
@@ -255,8 +284,8 @@ The resulting theme has the extracted hue and saturation. Add colors as usual:
|
|
|
255
284
|
|
|
256
285
|
```ts
|
|
257
286
|
brand.colors({
|
|
258
|
-
surface: {
|
|
259
|
-
text: { base: 'surface',
|
|
287
|
+
surface: { lightness: 97, saturation: 0.75 },
|
|
288
|
+
text: { base: 'surface', lightness: '-52', contrast: 'AAA' },
|
|
260
289
|
});
|
|
261
290
|
```
|
|
262
291
|
|
|
@@ -278,7 +307,7 @@ theme.tokens({ format: 'hsl' }); // → 'hsl(270.5, 45.2%, 95.8%)'
|
|
|
278
307
|
theme.tokens({ format: 'oklch' }); // → 'oklch(96.5% 0.0123 280.0)'
|
|
279
308
|
```
|
|
280
309
|
|
|
281
|
-
The `format` option works on all export methods: `theme.tokens()`, `theme.json()`, `palette.tokens()`, `palette.json()`, and standalone `glaze.color().token()` / `.json()`.
|
|
310
|
+
The `format` option works on all export methods: `theme.tokens()`, `theme.json()`, `theme.css()`, `palette.tokens()`, `palette.json()`, `palette.css()`, and standalone `glaze.color().token()` / `.json()`.
|
|
282
311
|
|
|
283
312
|
Available formats:
|
|
284
313
|
|
|
@@ -299,20 +328,20 @@ Modes control how colors adapt across schemes:
|
|
|
299
328
|
| `'fixed'` | Color stays recognizable. Only safety corrections. For brand buttons, CTAs. |
|
|
300
329
|
| `'static'` | No adaptation. Same value in every scheme. |
|
|
301
330
|
|
|
302
|
-
### How
|
|
331
|
+
### How Relative Lightness Adapts
|
|
303
332
|
|
|
304
|
-
**`auto` mode** —
|
|
333
|
+
**`auto` mode** — relative lightness sign flips in dark scheme:
|
|
305
334
|
|
|
306
335
|
```ts
|
|
307
|
-
// Light: surface L=97, text
|
|
336
|
+
// Light: surface L=97, text lightness='-52' → L=45 (dark text on light bg)
|
|
308
337
|
// Dark: surface inverts to L≈14, sign flips → L=14+52=66
|
|
309
|
-
//
|
|
338
|
+
// contrast solver may push further (light text on dark bg)
|
|
310
339
|
```
|
|
311
340
|
|
|
312
|
-
**`fixed` mode** — lightness is mapped (not inverted),
|
|
341
|
+
**`fixed` mode** — lightness is mapped (not inverted), relative sign preserved:
|
|
313
342
|
|
|
314
343
|
```ts
|
|
315
|
-
// Light: accent-fill L=52, accent-text
|
|
344
|
+
// Light: accent-fill L=52, accent-text lightness='+48' → L=100 (white on brand)
|
|
316
345
|
// Dark: accent-fill maps to L≈51.6, sign preserved → L≈99.6
|
|
317
346
|
```
|
|
318
347
|
|
|
@@ -367,7 +396,7 @@ Override individual colors (additive merge):
|
|
|
367
396
|
```ts
|
|
368
397
|
const danger = primary.extend({
|
|
369
398
|
hue: 23,
|
|
370
|
-
colors: { 'accent-fill': {
|
|
399
|
+
colors: { 'accent-fill': { lightness: 48, mode: 'fixed' } },
|
|
371
400
|
});
|
|
372
401
|
```
|
|
373
402
|
|
|
@@ -405,6 +434,53 @@ const data = palette.json({ prefix: true });
|
|
|
405
434
|
// }
|
|
406
435
|
```
|
|
407
436
|
|
|
437
|
+
### CSS Export
|
|
438
|
+
|
|
439
|
+
Export as CSS custom property declarations, grouped by scheme variant. Each variant is a string of `--name-color: value;` lines that you can wrap in your own selectors and media queries.
|
|
440
|
+
|
|
441
|
+
```ts
|
|
442
|
+
const css = theme.css();
|
|
443
|
+
// css.light → "--surface-color: rgb(...);\n--text-color: rgb(...);"
|
|
444
|
+
// css.dark → "--surface-color: rgb(...);\n--text-color: rgb(...);"
|
|
445
|
+
// css.lightContrast → "--surface-color: rgb(...);\n--text-color: rgb(...);"
|
|
446
|
+
// css.darkContrast → "--surface-color: rgb(...);\n--text-color: rgb(...);"
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
Use in a stylesheet:
|
|
450
|
+
|
|
451
|
+
```ts
|
|
452
|
+
const css = palette.css({ prefix: true });
|
|
453
|
+
|
|
454
|
+
const stylesheet = `
|
|
455
|
+
:root { ${css.light} }
|
|
456
|
+
@media (prefers-color-scheme: dark) {
|
|
457
|
+
:root { ${css.dark} }
|
|
458
|
+
}
|
|
459
|
+
`;
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
Options:
|
|
463
|
+
|
|
464
|
+
| Option | Default | Description |
|
|
465
|
+
|---|---|---|
|
|
466
|
+
| `format` | `'rgb'` | Color format (`'rgb'`, `'hsl'`, `'okhsl'`, `'oklch'`) |
|
|
467
|
+
| `suffix` | `'-color'` | Suffix appended to each CSS property name |
|
|
468
|
+
| `prefix` | — | (palette only) Same prefix behavior as `tokens()` |
|
|
469
|
+
|
|
470
|
+
```ts
|
|
471
|
+
// Custom suffix
|
|
472
|
+
theme.css({ suffix: '' });
|
|
473
|
+
// → "--surface: rgb(...);"
|
|
474
|
+
|
|
475
|
+
// Custom format
|
|
476
|
+
theme.css({ format: 'hsl' });
|
|
477
|
+
// → "--surface-color: hsl(...);"
|
|
478
|
+
|
|
479
|
+
// Palette with prefix
|
|
480
|
+
palette.css({ prefix: true });
|
|
481
|
+
// → "--primary-surface-color: rgb(...);\n--danger-surface-color: rgb(...);"
|
|
482
|
+
```
|
|
483
|
+
|
|
408
484
|
## Output Modes
|
|
409
485
|
|
|
410
486
|
Control which scheme variants appear in exports:
|
|
@@ -422,7 +498,7 @@ palette.tokens({ modes: { dark: true, highContrast: true } });
|
|
|
422
498
|
|
|
423
499
|
Resolution priority (highest first):
|
|
424
500
|
|
|
425
|
-
1. `tokens({ modes })` / `json({ modes })` — per-call override
|
|
501
|
+
1. `tokens({ modes })` / `json({ modes })` / `css({ ... })` — per-call override
|
|
426
502
|
2. `glaze.configure({ modes })` — global config
|
|
427
503
|
3. Built-in default: `{ dark: true, highContrast: false }`
|
|
428
504
|
|
|
@@ -446,33 +522,43 @@ glaze.configure({
|
|
|
446
522
|
## Color Definition Shape
|
|
447
523
|
|
|
448
524
|
```ts
|
|
525
|
+
type RelativeValue = `+${number}` | `-${number}`;
|
|
449
526
|
type HCPair<T> = T | [T, T]; // [normal, high-contrast]
|
|
450
527
|
|
|
451
528
|
interface ColorDef {
|
|
452
|
-
//
|
|
453
|
-
|
|
454
|
-
|
|
529
|
+
// Lightness
|
|
530
|
+
lightness?: HCPair<number | RelativeValue>;
|
|
531
|
+
// Number: absolute (0–100)
|
|
532
|
+
// String: relative to base ('+N' / '-N')
|
|
533
|
+
|
|
534
|
+
// Hue override
|
|
535
|
+
hue?: number | RelativeValue;
|
|
536
|
+
// Number: absolute (0–360)
|
|
537
|
+
// String: relative to theme seed ('+N' / '-N')
|
|
455
538
|
|
|
456
|
-
//
|
|
539
|
+
// Saturation factor (0–1, default: 1)
|
|
540
|
+
saturation?: number;
|
|
541
|
+
|
|
542
|
+
// Dependency
|
|
457
543
|
base?: string; // name of another color
|
|
458
|
-
contrast?: HCPair<
|
|
459
|
-
ensureContrast?: HCPair<MinContrast>; // ensures WCAG contrast ratio meets target floor
|
|
544
|
+
contrast?: HCPair<MinContrast>; // WCAG contrast ratio floor against base
|
|
460
545
|
|
|
461
546
|
// Adaptation mode
|
|
462
547
|
mode?: 'auto' | 'fixed' | 'static'; // default: 'auto'
|
|
463
548
|
}
|
|
464
549
|
```
|
|
465
550
|
|
|
466
|
-
|
|
551
|
+
A root color must have absolute `lightness` (a number). A dependent color must have `base`. Relative `lightness` (a string) requires `base`.
|
|
467
552
|
|
|
468
553
|
## Validation
|
|
469
554
|
|
|
470
555
|
| Condition | Behavior |
|
|
471
556
|
|---|---|
|
|
472
|
-
| Both `
|
|
557
|
+
| Both absolute `lightness` and `base` on same color | Warning, `lightness` takes precedence |
|
|
473
558
|
| `contrast` without `base` | Validation error |
|
|
474
|
-
| `
|
|
475
|
-
| `
|
|
559
|
+
| Relative `lightness` without `base` | Validation error |
|
|
560
|
+
| `lightness` resolves outside 0–100 | Clamp silently |
|
|
561
|
+
| `saturation` outside 0–1 | Clamp silently |
|
|
476
562
|
| Circular `base` references | Validation error |
|
|
477
563
|
| `base` references non-existent name | Validation error |
|
|
478
564
|
|
|
@@ -506,14 +592,14 @@ import { glaze } from '@tenphi/glaze';
|
|
|
506
592
|
const primary = glaze(280, 80);
|
|
507
593
|
|
|
508
594
|
primary.colors({
|
|
509
|
-
surface:
|
|
510
|
-
text:
|
|
511
|
-
border:
|
|
512
|
-
bg:
|
|
513
|
-
icon:
|
|
514
|
-
'accent-fill': {
|
|
515
|
-
'accent-text': { base: 'accent-fill',
|
|
516
|
-
disabled:
|
|
595
|
+
surface: { lightness: 97, saturation: 0.75 },
|
|
596
|
+
text: { base: 'surface', lightness: '-52', contrast: 'AAA' },
|
|
597
|
+
border: { base: 'surface', lightness: ['-7', '-20'], contrast: 'AA-large' },
|
|
598
|
+
bg: { lightness: 97, saturation: 0.75 },
|
|
599
|
+
icon: { lightness: 60, saturation: 0.94 },
|
|
600
|
+
'accent-fill': { lightness: 52, mode: 'fixed' },
|
|
601
|
+
'accent-text': { base: 'accent-fill', lightness: '+48', contrast: 'AA', mode: 'fixed' },
|
|
602
|
+
disabled: { lightness: 81, saturation: 0.4 },
|
|
517
603
|
});
|
|
518
604
|
|
|
519
605
|
const danger = primary.extend({ hue: 23 });
|
|
@@ -529,13 +615,18 @@ const tokens = palette.tokens({ prefix: true });
|
|
|
529
615
|
// Export as RGB for broader CSS compatibility
|
|
530
616
|
const rgbTokens = palette.tokens({ prefix: true, format: 'rgb' });
|
|
531
617
|
|
|
618
|
+
// Export as CSS custom properties (rgb format by default)
|
|
619
|
+
const css = palette.css({ prefix: true });
|
|
620
|
+
// css.light → "--primary-surface-color: rgb(...);\n--danger-surface-color: rgb(...);"
|
|
621
|
+
// css.dark → "--primary-surface-color: rgb(...);\n--danger-surface-color: rgb(...);"
|
|
622
|
+
|
|
532
623
|
// Save and restore a theme
|
|
533
624
|
const snapshot = primary.export();
|
|
534
625
|
const restored = glaze.from(snapshot);
|
|
535
626
|
|
|
536
627
|
// Create from an existing brand color
|
|
537
628
|
const brand = glaze.fromHex('#7a4dbf');
|
|
538
|
-
brand.colors({ surface: {
|
|
629
|
+
brand.colors({ surface: { lightness: 97 }, text: { base: 'surface', lightness: '-52' } });
|
|
539
630
|
```
|
|
540
631
|
|
|
541
632
|
## API Reference
|
|
@@ -567,6 +658,7 @@ brand.colors({ surface: { l: 97 }, text: { base: 'surface', contrast: 52 } });
|
|
|
567
658
|
| `theme.resolve()` | Resolve all colors |
|
|
568
659
|
| `theme.tokens(options?)` | Export as token map |
|
|
569
660
|
| `theme.json(options?)` | Export as plain JSON |
|
|
661
|
+
| `theme.css(options?)` | Export as CSS custom property declarations |
|
|
570
662
|
|
|
571
663
|
### Global Configuration
|
|
572
664
|
|