@tenphi/glaze 0.0.0-snapshot.4c063ef → 0.0.0-snapshot.575cb1c
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 +228 -35
- package/dist/index.cjs +323 -70
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +123 -22
- package/dist/index.d.mts +123 -22
- package/dist/index.mjs +322 -71
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -22,6 +22,7 @@ Glaze generates robust **light**, **dark**, and **high-contrast** color schemes
|
|
|
22
22
|
|
|
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
|
+
- **Mix colors** — blend two colors with OKHSL or sRGB interpolation, opaque or transparent, with optional contrast solving
|
|
25
26
|
- **Shadow colors** — OKHSL-native shadow computation with automatic alpha, fg/bg tinting, and per-scheme adaptation
|
|
26
27
|
- **Light + Dark + High-Contrast** — all schemes from one definition
|
|
27
28
|
- **Per-color hue override** — absolute or relative hue shifts within a theme
|
|
@@ -70,8 +71,8 @@ const success = primary.extend({ hue: 157 });
|
|
|
70
71
|
|
|
71
72
|
// Compose into a palette and export
|
|
72
73
|
const palette = glaze.palette({ primary, danger, success });
|
|
73
|
-
const tokens = palette.tokens({
|
|
74
|
-
// → { light: { 'primary-surface': 'okhsl(...)',
|
|
74
|
+
const tokens = palette.tokens({ primary: 'primary' });
|
|
75
|
+
// → { light: { 'primary-surface': 'okhsl(...)', 'surface': 'okhsl(...)', ... }, dark: { ... } }
|
|
75
76
|
```
|
|
76
77
|
|
|
77
78
|
## Core Concepts
|
|
@@ -193,6 +194,8 @@ A single value applies to both modes. All control is local and explicit.
|
|
|
193
194
|
'muted': { base: 'surface', lightness: ['-35', '-50'], contrast: ['AA-large', 'AA'] }
|
|
194
195
|
```
|
|
195
196
|
|
|
197
|
+
**Full lightness spectrum in HC mode:** In high-contrast variants, the `lightLightness` and `darkLightness` window constraints are bypassed entirely. Colors can reach the full 0–100 lightness range, maximizing perceivable contrast. Normal (non-HC) variants continue to use the configured windows.
|
|
198
|
+
|
|
196
199
|
## Theme Color Management
|
|
197
200
|
|
|
198
201
|
### Adding Colors
|
|
@@ -413,6 +416,139 @@ const css = glaze.format(v, 'oklch');
|
|
|
413
416
|
}
|
|
414
417
|
```
|
|
415
418
|
|
|
419
|
+
## Mix Colors
|
|
420
|
+
|
|
421
|
+
Mix colors blend two existing colors together. Use them for hover overlays, tints, shades, and any derived color that sits between two reference colors.
|
|
422
|
+
|
|
423
|
+
### Opaque Mix
|
|
424
|
+
|
|
425
|
+
Produces a solid color by interpolating between `base` and `target`:
|
|
426
|
+
|
|
427
|
+
```ts
|
|
428
|
+
theme.colors({
|
|
429
|
+
surface: { lightness: 95 },
|
|
430
|
+
accent: { lightness: 30 },
|
|
431
|
+
|
|
432
|
+
// 30% of the way from surface toward accent
|
|
433
|
+
tint: { type: 'mix', base: 'surface', target: 'accent', value: 30 },
|
|
434
|
+
});
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
- `value` — mix ratio 0–100 (0 = pure base, 100 = pure target)
|
|
438
|
+
- The result is a fully opaque color (alpha = 1)
|
|
439
|
+
- Adapts to light/dark/HC schemes automatically via the resolved base and target
|
|
440
|
+
|
|
441
|
+
### Transparent Mix
|
|
442
|
+
|
|
443
|
+
Produces the target color with a controlled opacity — useful for hover overlays:
|
|
444
|
+
|
|
445
|
+
```ts
|
|
446
|
+
theme.colors({
|
|
447
|
+
surface: { lightness: 95 },
|
|
448
|
+
black: { lightness: 0, saturation: 0 },
|
|
449
|
+
|
|
450
|
+
hover: {
|
|
451
|
+
type: 'mix',
|
|
452
|
+
base: 'surface',
|
|
453
|
+
target: 'black',
|
|
454
|
+
value: 8,
|
|
455
|
+
blend: 'transparent',
|
|
456
|
+
},
|
|
457
|
+
});
|
|
458
|
+
// hover → target color (black) with alpha = 0.08
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
The output color has `h`, `s`, `l` from the target and `alpha = value / 100`.
|
|
462
|
+
|
|
463
|
+
### Blend Space
|
|
464
|
+
|
|
465
|
+
By default, opaque mixing interpolates in OKHSL (perceptually uniform, consistent with Glaze's model). Use `space: 'srgb'` for linear sRGB interpolation, which matches browser compositing:
|
|
466
|
+
|
|
467
|
+
```ts
|
|
468
|
+
theme.colors({
|
|
469
|
+
surface: { lightness: 95 },
|
|
470
|
+
accent: { lightness: 30 },
|
|
471
|
+
|
|
472
|
+
// sRGB blend — matches what the browser would render
|
|
473
|
+
hover: { type: 'mix', base: 'surface', target: 'accent', value: 20, space: 'srgb' },
|
|
474
|
+
});
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
| Space | Behavior | Best for |
|
|
478
|
+
|---|---|---|
|
|
479
|
+
| `'okhsl'` (default) | Perceptually uniform OKHSL interpolation | Design token derivation |
|
|
480
|
+
| `'srgb'` | Linear sRGB channel interpolation | Matching browser compositing |
|
|
481
|
+
|
|
482
|
+
The `space` option only affects opaque blending. Transparent blending always composites in linear sRGB (matching browser alpha compositing).
|
|
483
|
+
|
|
484
|
+
### Contrast Solving
|
|
485
|
+
|
|
486
|
+
Mix colors support the same `contrast` prop as regular colors. The solver adjusts the mix ratio (opaque) or opacity (transparent) to meet the WCAG target:
|
|
487
|
+
|
|
488
|
+
```ts
|
|
489
|
+
theme.colors({
|
|
490
|
+
surface: { lightness: 95 },
|
|
491
|
+
accent: { lightness: 30 },
|
|
492
|
+
|
|
493
|
+
// Ensure the mixed color has at least AA contrast against surface
|
|
494
|
+
tint: {
|
|
495
|
+
type: 'mix',
|
|
496
|
+
base: 'surface',
|
|
497
|
+
target: 'accent',
|
|
498
|
+
value: 10,
|
|
499
|
+
contrast: 'AA',
|
|
500
|
+
},
|
|
501
|
+
|
|
502
|
+
// Ensure the transparent overlay has at least 3:1 contrast
|
|
503
|
+
overlay: {
|
|
504
|
+
type: 'mix',
|
|
505
|
+
base: 'surface',
|
|
506
|
+
target: 'accent',
|
|
507
|
+
value: 5,
|
|
508
|
+
blend: 'transparent',
|
|
509
|
+
contrast: 3,
|
|
510
|
+
},
|
|
511
|
+
});
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
### High-Contrast Pairs
|
|
515
|
+
|
|
516
|
+
Both `value` and `contrast` support `[normal, highContrast]` pairs:
|
|
517
|
+
|
|
518
|
+
```ts
|
|
519
|
+
theme.colors({
|
|
520
|
+
surface: { lightness: 95 },
|
|
521
|
+
accent: { lightness: 30 },
|
|
522
|
+
|
|
523
|
+
tint: {
|
|
524
|
+
type: 'mix',
|
|
525
|
+
base: 'surface',
|
|
526
|
+
target: 'accent',
|
|
527
|
+
value: [20, 40], // stronger mix in high-contrast mode
|
|
528
|
+
contrast: [3, 'AAA'], // stricter contrast in high-contrast mode
|
|
529
|
+
},
|
|
530
|
+
});
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
### Achromatic Colors
|
|
534
|
+
|
|
535
|
+
When mixing with achromatic colors (saturation near zero, e.g., white or black) in `okhsl` space, the hue comes from whichever color has saturation. This prevents meaningless hue artifacts and matches CSS `color-mix()` "missing component" behavior. For purely achromatic mixes, prefer `space: 'srgb'` where hue is irrelevant.
|
|
536
|
+
|
|
537
|
+
### Mix Chaining
|
|
538
|
+
|
|
539
|
+
Mix colors can reference other mix colors, enabling multi-step derivations:
|
|
540
|
+
|
|
541
|
+
```ts
|
|
542
|
+
theme.colors({
|
|
543
|
+
white: { lightness: 100, saturation: 0 },
|
|
544
|
+
black: { lightness: 0, saturation: 0 },
|
|
545
|
+
gray: { type: 'mix', base: 'white', target: 'black', value: 50, space: 'srgb' },
|
|
546
|
+
lightGray: { type: 'mix', base: 'white', target: 'gray', value: 50, space: 'srgb' },
|
|
547
|
+
});
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
Mix colors cannot reference shadow colors (same restriction as regular dependent colors).
|
|
551
|
+
|
|
416
552
|
## Output Formats
|
|
417
553
|
|
|
418
554
|
Control the color format in exports with the `format` option:
|
|
@@ -467,7 +603,7 @@ Modes control how colors adapt across schemes:
|
|
|
467
603
|
|
|
468
604
|
```ts
|
|
469
605
|
// Light: surface L=97, text lightness='-52' → L=45 (dark text on light bg)
|
|
470
|
-
// Dark: surface inverts to L≈
|
|
606
|
+
// Dark: surface inverts to L≈29 (power curve), sign flips → L=29+52=81
|
|
471
607
|
// contrast solver may push further (light text on dark bg)
|
|
472
608
|
```
|
|
473
609
|
|
|
@@ -484,14 +620,14 @@ Modes control how colors adapt across schemes:
|
|
|
484
620
|
|
|
485
621
|
### Lightness
|
|
486
622
|
|
|
487
|
-
|
|
623
|
+
Absolute lightness values (both root colors and dependent colors with absolute lightness) are mapped linearly within the configured `lightLightness` window:
|
|
488
624
|
|
|
489
625
|
```ts
|
|
490
626
|
const [lo, hi] = lightLightness; // default: [10, 100]
|
|
491
627
|
const mappedL = (lightness * (hi - lo)) / 100 + lo;
|
|
492
628
|
```
|
|
493
629
|
|
|
494
|
-
Both `auto` and `fixed` modes use the same linear formula. `static` mode
|
|
630
|
+
Both `auto` and `fixed` modes use the same linear formula. `static` mode and high-contrast variants bypass the mapping entirely (identity: `mappedL = l`).
|
|
495
631
|
|
|
496
632
|
| Color | Raw L | Mapped L (default [10, 100]) |
|
|
497
633
|
|---|---|---|
|
|
@@ -503,24 +639,29 @@ Both `auto` and `fixed` modes use the same linear formula. `static` mode bypasse
|
|
|
503
639
|
|
|
504
640
|
### Lightness
|
|
505
641
|
|
|
506
|
-
**`auto`** — inverted within the configured window:
|
|
642
|
+
**`auto`** — inverted with a power curve within the configured window:
|
|
507
643
|
|
|
508
644
|
```ts
|
|
509
645
|
const [lo, hi] = darkLightness; // default: [15, 95]
|
|
510
|
-
const
|
|
646
|
+
const d = (100 - lightness) / 100;
|
|
647
|
+
const invertedL = lo + (hi - lo) * Math.pow(d, darkCurve); // darkCurve default: 0.5
|
|
511
648
|
```
|
|
512
649
|
|
|
513
|
-
|
|
650
|
+
The `darkCurve` exponent (default `0.5`) expands small light-theme deltas near white into larger usable deltas in dark mode. This preserves subtle surface hierarchy (e.g. L=97 vs L=95) that would otherwise collapse to near-identical dark values. Set `darkCurve: 1` for linear (legacy) behavior.
|
|
651
|
+
|
|
652
|
+
**`fixed`** — mapped without inversion (not affected by `darkCurve`):
|
|
514
653
|
|
|
515
654
|
```ts
|
|
516
655
|
const mappedL = (lightness * (hi - lo)) / 100 + lo;
|
|
517
656
|
```
|
|
518
657
|
|
|
519
|
-
| Color | Light L | Auto (
|
|
520
|
-
|
|
521
|
-
| surface (L=97) | 97 | 17.4 | 92.6 |
|
|
522
|
-
| accent-fill (L=52) | 52 | 53.4 | 56.6 |
|
|
523
|
-
| accent-text (L=100) | 100 | 15 | 95 |
|
|
658
|
+
| Color | Light L | Auto (curve=0.5) | Auto (curve=1, linear) | Fixed (mapped) |
|
|
659
|
+
|---|---|---|---|---|
|
|
660
|
+
| surface (L=97) | 97 | 28.9 | 17.4 | 92.6 |
|
|
661
|
+
| accent-fill (L=52) | 52 | 70.4 | 53.4 | 56.6 |
|
|
662
|
+
| accent-text (L=100) | 100 | 15 | 15 | 95 |
|
|
663
|
+
|
|
664
|
+
In high-contrast variants, the `darkLightness` window is bypassed. Auto uses pure inversion (`100 - L`), fixed uses identity (`L`). This allows HC colors to reach the full 0–100 range.
|
|
524
665
|
|
|
525
666
|
### Saturation
|
|
526
667
|
|
|
@@ -560,12 +701,12 @@ Combine multiple themes into a single palette:
|
|
|
560
701
|
const palette = glaze.palette({ primary, danger, success, warning });
|
|
561
702
|
```
|
|
562
703
|
|
|
563
|
-
###
|
|
704
|
+
### Prefix Behavior
|
|
564
705
|
|
|
565
|
-
|
|
706
|
+
Palette export methods (`tokens()`, `tasty()`, `css()`) default to `prefix: true` — all tokens are automatically prefixed with the theme name to avoid collisions:
|
|
566
707
|
|
|
567
708
|
```ts
|
|
568
|
-
const tokens = palette.tokens(
|
|
709
|
+
const tokens = palette.tokens();
|
|
569
710
|
// → {
|
|
570
711
|
// light: { 'primary-surface': 'okhsl(...)', 'danger-surface': 'okhsl(...)' },
|
|
571
712
|
// dark: { 'primary-surface': 'okhsl(...)', 'danger-surface': 'okhsl(...)' },
|
|
@@ -578,15 +719,44 @@ Custom prefix mapping:
|
|
|
578
719
|
palette.tokens({ prefix: { primary: 'brand-', danger: 'error-' } });
|
|
579
720
|
```
|
|
580
721
|
|
|
722
|
+
To disable prefixing entirely, pass `prefix: false` explicitly. Note that tokens with the same name will overwrite each other (last theme wins).
|
|
723
|
+
|
|
724
|
+
### Primary Theme
|
|
725
|
+
|
|
726
|
+
Use the `primary` option to designate one theme as the primary. Its tokens are duplicated without prefix, providing convenient short aliases alongside the prefixed versions:
|
|
727
|
+
|
|
728
|
+
```ts
|
|
729
|
+
const palette = glaze.palette({ primary, danger, success });
|
|
730
|
+
const tokens = palette.tokens({ primary: 'primary' });
|
|
731
|
+
// → {
|
|
732
|
+
// light: {
|
|
733
|
+
// 'primary-surface': 'okhsl(...)', // prefixed (all themes)
|
|
734
|
+
// 'danger-surface': 'okhsl(...)',
|
|
735
|
+
// 'success-surface': 'okhsl(...)',
|
|
736
|
+
// 'surface': 'okhsl(...)', // unprefixed alias (primary only)
|
|
737
|
+
// },
|
|
738
|
+
// }
|
|
739
|
+
```
|
|
740
|
+
|
|
741
|
+
The `primary` option works on `tokens()`, `tasty()`, and `css()`. It combines with any prefix mode — when using a custom prefix map, primary tokens are still duplicated without prefix:
|
|
742
|
+
|
|
743
|
+
```ts
|
|
744
|
+
palette.tokens({ prefix: { primary: 'p-', danger: 'd-' }, primary: 'primary' });
|
|
745
|
+
// → 'p-surface' + 'surface' (alias) + 'd-surface'
|
|
746
|
+
```
|
|
747
|
+
|
|
748
|
+
An error is thrown if the primary name doesn't match any theme in the palette.
|
|
749
|
+
|
|
581
750
|
### Tasty Export (for [Tasty](https://cube-ui-kit.vercel.app/?path=/docs/tasty-documentation--docs) style system)
|
|
582
751
|
|
|
583
752
|
The `tasty()` method exports tokens in the [Tasty](https://cube-ui-kit.vercel.app/?path=/docs/tasty-documentation--docs) style-to-state binding format — `#name` color token keys with state aliases (`''`, `@dark`, etc.):
|
|
584
753
|
|
|
585
754
|
```ts
|
|
586
|
-
const tastyTokens = palette.tasty({
|
|
755
|
+
const tastyTokens = palette.tasty({ primary: 'primary' });
|
|
587
756
|
// → {
|
|
588
757
|
// '#primary-surface': { '': 'okhsl(...)', '@dark': 'okhsl(...)' },
|
|
589
758
|
// '#danger-surface': { '': 'okhsl(...)', '@dark': 'okhsl(...)' },
|
|
759
|
+
// '#surface': { '': 'okhsl(...)', '@dark': 'okhsl(...)' }, // alias
|
|
590
760
|
// }
|
|
591
761
|
```
|
|
592
762
|
|
|
@@ -653,8 +823,10 @@ palette.tasty({ states: { dark: '@dark', highContrast: '@hc' } });
|
|
|
653
823
|
|
|
654
824
|
### JSON Export (Framework-Agnostic)
|
|
655
825
|
|
|
826
|
+
JSON export groups by theme name (no prefix needed):
|
|
827
|
+
|
|
656
828
|
```ts
|
|
657
|
-
const data = palette.json(
|
|
829
|
+
const data = palette.json();
|
|
658
830
|
// → {
|
|
659
831
|
// primary: { surface: { light: 'okhsl(...)', dark: 'okhsl(...)' } },
|
|
660
832
|
// danger: { surface: { light: 'okhsl(...)', dark: 'okhsl(...)' } },
|
|
@@ -676,7 +848,7 @@ const css = theme.css();
|
|
|
676
848
|
Use in a stylesheet:
|
|
677
849
|
|
|
678
850
|
```ts
|
|
679
|
-
const css = palette.css({
|
|
851
|
+
const css = palette.css({ primary: 'primary' });
|
|
680
852
|
|
|
681
853
|
const stylesheet = `
|
|
682
854
|
:root { ${css.light} }
|
|
@@ -692,7 +864,8 @@ Options:
|
|
|
692
864
|
|---|---|---|
|
|
693
865
|
| `format` | `'rgb'` | Color format (`'rgb'`, `'hsl'`, `'okhsl'`, `'oklch'`) |
|
|
694
866
|
| `suffix` | `'-color'` | Suffix appended to each CSS property name |
|
|
695
|
-
| `prefix` |
|
|
867
|
+
| `prefix` | `true` (palette) | (palette only) `true` uses `"<themeName>-"`, or provide a custom map |
|
|
868
|
+
| `primary` | — | (palette only) Theme name to duplicate without prefix |
|
|
696
869
|
|
|
697
870
|
```ts
|
|
698
871
|
// Custom suffix
|
|
@@ -703,9 +876,9 @@ theme.css({ suffix: '' });
|
|
|
703
876
|
theme.css({ format: 'hsl' });
|
|
704
877
|
// → "--surface-color: hsl(...);"
|
|
705
878
|
|
|
706
|
-
// Palette with
|
|
707
|
-
palette.css({
|
|
708
|
-
// → "--primary-surface-color: rgb(...);\n--danger-surface-color: rgb(...);"
|
|
879
|
+
// Palette with primary
|
|
880
|
+
palette.css({ primary: 'primary' });
|
|
881
|
+
// → "--primary-surface-color: rgb(...);\n--surface-color: rgb(...);\n--danger-surface-color: rgb(...);"
|
|
709
882
|
```
|
|
710
883
|
|
|
711
884
|
## Output Modes
|
|
@@ -738,9 +911,10 @@ Resolution priority (highest first):
|
|
|
738
911
|
|
|
739
912
|
```ts
|
|
740
913
|
glaze.configure({
|
|
741
|
-
lightLightness: [10, 100], // Light scheme lightness window [lo, hi]
|
|
742
|
-
darkLightness: [15, 95], // Dark scheme lightness window [lo, hi]
|
|
914
|
+
lightLightness: [10, 100], // Light scheme lightness window [lo, hi] (bypassed in HC)
|
|
915
|
+
darkLightness: [15, 95], // Dark scheme lightness window [lo, hi] (bypassed in HC)
|
|
743
916
|
darkDesaturation: 0.1, // Saturation reduction in dark scheme (0–1)
|
|
917
|
+
darkCurve: 0.5, // Power-curve exponent for dark auto-inversion (0–1)
|
|
744
918
|
states: {
|
|
745
919
|
dark: '@dark', // State alias for dark mode tokens
|
|
746
920
|
highContrast: '@high-contrast',
|
|
@@ -758,10 +932,10 @@ glaze.configure({
|
|
|
758
932
|
|
|
759
933
|
## Color Definition Shape
|
|
760
934
|
|
|
761
|
-
`ColorDef` is a discriminated union of regular colors and
|
|
935
|
+
`ColorDef` is a discriminated union of regular colors, shadow colors, and mix colors:
|
|
762
936
|
|
|
763
937
|
```ts
|
|
764
|
-
type ColorDef = RegularColorDef | ShadowColorDef;
|
|
938
|
+
type ColorDef = RegularColorDef | ShadowColorDef | MixColorDef;
|
|
765
939
|
|
|
766
940
|
interface RegularColorDef {
|
|
767
941
|
lightness?: HCPair<number | RelativeValue>;
|
|
@@ -780,15 +954,24 @@ interface ShadowColorDef {
|
|
|
780
954
|
intensity: HCPair<number>; // 0–100
|
|
781
955
|
tuning?: ShadowTuning;
|
|
782
956
|
}
|
|
957
|
+
|
|
958
|
+
interface MixColorDef {
|
|
959
|
+
type: 'mix';
|
|
960
|
+
base: string; // "from" color name
|
|
961
|
+
target: string; // "to" color name
|
|
962
|
+
value: HCPair<number>; // 0–100 (mix ratio or opacity)
|
|
963
|
+
blend?: 'opaque' | 'transparent'; // default: 'opaque'
|
|
964
|
+
space?: 'okhsl' | 'srgb'; // default: 'okhsl'
|
|
965
|
+
contrast?: HCPair<MinContrast>;
|
|
966
|
+
}
|
|
783
967
|
```
|
|
784
968
|
|
|
785
|
-
A root color must have absolute `lightness` (a number). A dependent color must have `base`. Relative `lightness` (a string) requires `base`. Shadow colors use `type: 'shadow'` and must reference a non-shadow `bg` color.
|
|
969
|
+
A root color must have absolute `lightness` (a number). A dependent color must have `base`. Relative `lightness` (a string) requires `base`. Shadow colors use `type: 'shadow'` and must reference a non-shadow `bg` color. Mix colors use `type: 'mix'` and must reference two non-shadow colors.
|
|
786
970
|
|
|
787
971
|
## Validation
|
|
788
972
|
|
|
789
973
|
| Condition | Behavior |
|
|
790
974
|
|---|---|
|
|
791
|
-
| Both absolute `lightness` and `base` on same color | Warning, `lightness` takes precedence |
|
|
792
975
|
| `contrast` without `base` | Validation error |
|
|
793
976
|
| Relative `lightness` without `base` | Validation error |
|
|
794
977
|
| `lightness` resolves outside 0–100 | Clamp silently |
|
|
@@ -802,6 +985,12 @@ A root color must have absolute `lightness` (a number). A dependent color must h
|
|
|
802
985
|
| Regular color `base` references a shadow color | Validation error |
|
|
803
986
|
| Shadow `intensity` outside 0–100 | Clamp silently |
|
|
804
987
|
| `contrast` + `opacity` combined | Warning |
|
|
988
|
+
| Mix `base` references non-existent color | Validation error |
|
|
989
|
+
| Mix `target` references non-existent color | Validation error |
|
|
990
|
+
| Mix `base` references a shadow color | Validation error |
|
|
991
|
+
| Mix `target` references a shadow color | Validation error |
|
|
992
|
+
| Mix `value` outside 0–100 | Clamp silently |
|
|
993
|
+
| Circular references involving mix colors | Validation error |
|
|
805
994
|
|
|
806
995
|
## Advanced: Color Math Utilities
|
|
807
996
|
|
|
@@ -847,6 +1036,10 @@ primary.colors({
|
|
|
847
1036
|
'shadow-md': { type: 'shadow', bg: 'surface', fg: 'text', intensity: 10 },
|
|
848
1037
|
'shadow-lg': { type: 'shadow', bg: 'surface', fg: 'text', intensity: 20 },
|
|
849
1038
|
|
|
1039
|
+
// Mix colors — hover overlays and tints
|
|
1040
|
+
'hover': { type: 'mix', base: 'surface', target: 'accent-fill', value: 8, blend: 'transparent' },
|
|
1041
|
+
'tint': { type: 'mix', base: 'surface', target: 'accent-fill', value: 20 },
|
|
1042
|
+
|
|
850
1043
|
// Fixed-alpha overlay
|
|
851
1044
|
overlay: { lightness: 0, opacity: 0.5 },
|
|
852
1045
|
});
|
|
@@ -858,16 +1051,16 @@ const note = primary.extend({ hue: 302 });
|
|
|
858
1051
|
|
|
859
1052
|
const palette = glaze.palette({ primary, danger, success, warning, note });
|
|
860
1053
|
|
|
861
|
-
// Export as flat token map grouped by variant
|
|
862
|
-
const tokens = palette.tokens({
|
|
863
|
-
// tokens.light → { 'primary-surface': '
|
|
1054
|
+
// Export as flat token map grouped by variant (prefix defaults to true)
|
|
1055
|
+
const tokens = palette.tokens({ primary: 'primary' });
|
|
1056
|
+
// tokens.light → { 'primary-surface': '...', 'surface': '...', 'danger-surface': '...' }
|
|
864
1057
|
|
|
865
1058
|
// Export as tasty style-to-state bindings (for Tasty style system)
|
|
866
|
-
const tastyTokens = palette.tasty({
|
|
1059
|
+
const tastyTokens = palette.tasty({ primary: 'primary' });
|
|
867
1060
|
|
|
868
1061
|
// Export as CSS custom properties (rgb format by default)
|
|
869
|
-
const css = palette.css({
|
|
870
|
-
// css.light → "--primary-surface-color: rgb(...);\n--
|
|
1062
|
+
const css = palette.css({ primary: 'primary' });
|
|
1063
|
+
// css.light → "--primary-surface-color: rgb(...);\n--surface-color: rgb(...);\n--danger-surface-color: rgb(...);"
|
|
871
1064
|
|
|
872
1065
|
// Standalone shadow computation
|
|
873
1066
|
const v = glaze.shadow({ bg: '#f0eef5', fg: '#1a1a2e', intensity: 10 });
|