okchroma 0.3.1 → 0.4.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-lib/index.cjs +21 -16
- package/dist-lib/index.mjs +21 -16
- package/dist-lib/types/engine/cssRender.d.ts +2 -1
- package/dist-lib/types/index.d.ts +2 -2
- package/package.json +1 -1
- package/tokens/semantic.css +43 -51
package/dist-lib/index.cjs
CHANGED
|
@@ -32,6 +32,7 @@ __export(index_exports, {
|
|
|
32
32
|
RESOLVER_ID: () => RESOLVER_ID,
|
|
33
33
|
SCALE_STOP_COUNT: () => SCALE_STOP_COUNT,
|
|
34
34
|
SCRIM_ALPHA: () => SCRIM_ALPHA,
|
|
35
|
+
SCRIM_VAR: () => SCRIM_VAR,
|
|
35
36
|
SECONDARY_DISTINCT_DELTA_E: () => SECONDARY_DISTINCT_DELTA_E,
|
|
36
37
|
SHADOW_ALPHAS: () => SHADOW_ALPHAS,
|
|
37
38
|
SIGNALS: () => SIGNALS2,
|
|
@@ -59,6 +60,7 @@ __export(index_exports, {
|
|
|
59
60
|
generateScale: () => generateScale,
|
|
60
61
|
generateSubtleSecondary: () => generateSubtleSecondary,
|
|
61
62
|
neutralCss: () => neutralCss,
|
|
63
|
+
neutralTintHue: () => neutralTintHue,
|
|
62
64
|
pageStopFor: () => pageStopFor,
|
|
63
65
|
parseToken: () => parseToken,
|
|
64
66
|
resolveBrand: () => resolveBrand,
|
|
@@ -2717,6 +2719,12 @@ function generateScale(hex, scaleName, forcedArchetype, opts) {
|
|
|
2717
2719
|
pen100Dark: penPole(dark, 1)
|
|
2718
2720
|
};
|
|
2719
2721
|
}
|
|
2722
|
+
function neutralTintHue(primaryH, source, secondaryH, customHex) {
|
|
2723
|
+
if (source === "secondary" && secondaryH !== void 0) return secondaryH;
|
|
2724
|
+
if (source === "custom" && customHex && /^#?[0-9a-fA-F]{6}$/.test(customHex))
|
|
2725
|
+
return hexToOklch(customHex.startsWith("#") ? customHex : `#${customHex}`).H;
|
|
2726
|
+
return primaryH;
|
|
2727
|
+
}
|
|
2720
2728
|
function generateNeutralScale(brandH, level = "default", contrastProfile) {
|
|
2721
2729
|
const h = (brandH % 360 + 360) % 360;
|
|
2722
2730
|
const { r, g: g2, b } = oklchToSrgbUnclamped(0.5, 6e-3, h);
|
|
@@ -3522,9 +3530,12 @@ var SHADOW_ALPHAS = {
|
|
|
3522
3530
|
var SCRIM_ALPHA = 0.6;
|
|
3523
3531
|
var DISABLED_OPACITY = 0.38;
|
|
3524
3532
|
var TRANSPARENT_VAR = "--alpha-transparent";
|
|
3533
|
+
var SCRIM_VAR = "--abs-black-060";
|
|
3525
3534
|
var offsetRgba = (rung, mode) => mode === "light" ? `rgba(0, 0, 0, ${OFFSET_ALPHAS[rung]})` : `rgba(255, 255, 255, ${OFFSET_ALPHAS[rung]})`;
|
|
3526
3535
|
var alphaRootVars = (mode) => [
|
|
3527
3536
|
` ${TRANSPARENT_VAR}: transparent;`,
|
|
3537
|
+
// mode-invariant like transparent; repeated in the dark block to keep the set together
|
|
3538
|
+
` ${SCRIM_VAR}: rgba(0, 0, 0, ${SCRIM_ALPHA});`,
|
|
3528
3539
|
...Object.keys(OFFSET_ALPHAS).map(Number).sort((a, b) => a - b).map((r) => ` ${offsetVarName(r)}: ${offsetRgba(r, mode)};`),
|
|
3529
3540
|
// the toward-bg ladder (the 2026-08-29 inverse ladder, renamed 2026-08-31): the
|
|
3530
3541
|
// same rungs, pole flipped per mode — state layers for INVERTED grounds (never
|
|
@@ -3540,7 +3551,7 @@ function ctaNeedsBorder(s, mode, page) {
|
|
|
3540
3551
|
if (!page) return false;
|
|
3541
3552
|
return ctaPageLc(s, mode, page) < CTA_BORDER_LC_FLOOR;
|
|
3542
3553
|
}
|
|
3543
|
-
function brandKindBody(prefix, s, mode, page) {
|
|
3554
|
+
function brandKindBody(prefix, s, mode, page, on = prefix === CSS_NEUTRAL ? "soft" : "solid") {
|
|
3544
3555
|
const stops = mode === "light" ? s.light : s.dark;
|
|
3545
3556
|
const f = ctaFamilyOf(s, mode);
|
|
3546
3557
|
const onCta = mode === "light" ? s.onFillTextIsWhite : s.onFillTextIsWhiteDark;
|
|
@@ -3559,10 +3570,10 @@ function brandKindBody(prefix, s, mode, page) {
|
|
|
3559
3570
|
// button text takes the pole AT ALPHA like the default-model secondary's — composited
|
|
3560
3571
|
// over whatever state the fill is in, so hover/pressed carry their own legibility. Same
|
|
3561
3572
|
// register both families (SOFT_ON_CTA_ALPHA), so both alias the ONE system/alpha/ink
|
|
3562
|
-
// primitive.
|
|
3563
|
-
//
|
|
3564
|
-
//
|
|
3565
|
-
|
|
3573
|
+
// primitive. The neutral's is unconditional (the parameter default); the secondary's is
|
|
3574
|
+
// the caller's per-mode verdict. Loud fills (brand, signals, the cta escape) keep the
|
|
3575
|
+
// solid pole.
|
|
3576
|
+
on === "soft" ? ` --${prefix}-stamp-on: rgba(${onCta ? "255, 255, 255" : "0, 0, 0"}, ${SOFT_ON_CTA_ALPHA[mode]});` : ` --${prefix}-stamp-on: ${onColor(onCta)};`
|
|
3566
3577
|
];
|
|
3567
3578
|
}
|
|
3568
3579
|
function ctaFamilyOf(s, mode) {
|
|
@@ -3629,7 +3640,8 @@ function signalsCss(contrastProfile) {
|
|
|
3629
3640
|
// the system alpha variables every family's cta-border aliases (owner 2026-07-29) — this is
|
|
3630
3641
|
// the engine's one global :root, the CSS counterpart of the Figma side's system/alpha/* rows.
|
|
3631
3642
|
// Emitted in BOTH blocks because the offset rungs are scheme-DIVERGENT (black in light,
|
|
3632
|
-
// white in dark); --alpha-transparent
|
|
3643
|
+
// white in dark); --alpha-transparent and the scrim (both mode-invariant) repeat
|
|
3644
|
+
// harmlessly and keep the set together.
|
|
3633
3645
|
...alphaRootVars("light"),
|
|
3634
3646
|
...lightBlocks,
|
|
3635
3647
|
`}`,
|
|
@@ -3678,8 +3690,9 @@ function brandCss(slug, displayName, r, secondary, noteSuffix = "", neutralLevel
|
|
|
3678
3690
|
alias("stamp-on")
|
|
3679
3691
|
];
|
|
3680
3692
|
};
|
|
3681
|
-
const
|
|
3682
|
-
const
|
|
3693
|
+
const secondaryOn = (mode) => secondary && secondaryStyle !== "outline" && softOnCtaPasses(secondary, mode) ? "soft" : "solid";
|
|
3694
|
+
const secondaryLight = secondary ? brandKindBody(CSS_SECONDARY, secondary, "light", page.light, secondaryOn("light")) : mirrorBody(CSS_SECONDARY, "light");
|
|
3695
|
+
const secondaryDark = secondary ? brandKindBody(CSS_SECONDARY, secondary, "dark", page.dark, secondaryOn("dark")) : mirrorBody(CSS_SECONDARY, "dark");
|
|
3683
3696
|
const brandIdentity = ` --${CSS_BRAND}-identity: ${scale.identityHex};`;
|
|
3684
3697
|
const secondaryIdentity = secondary ? ` --${CSS_SECONDARY}-identity: ${secondary.identityHex};` : ` --${CSS_SECONDARY}-identity: var(--${CSS_BRAND}-identity);`;
|
|
3685
3698
|
const p0hex = (s, fallback) => s ? stopHex(s) : fallback;
|
|
@@ -3713,12 +3726,6 @@ function brandCss(slug, displayName, r, secondary, noteSuffix = "", neutralLevel
|
|
|
3713
3726
|
` --${CSS_BRAND}-stamp-on: ${onColor(esc.onFillIsWhite)};`
|
|
3714
3727
|
];
|
|
3715
3728
|
};
|
|
3716
|
-
const softOnCta = (mode) => {
|
|
3717
|
-
if (!secondary || secondaryStyle === "outline") return [];
|
|
3718
|
-
if (!softOnCtaPasses(secondary, mode)) return [];
|
|
3719
|
-
const white = mode === "light" ? secondary.onFillTextIsWhite : secondary.onFillTextIsWhiteDark;
|
|
3720
|
-
return [` --${CSS_SECONDARY}-stamp-on: rgba(${white ? "255, 255, 255" : "0, 0, 0"}, ${SOFT_ON_CTA_ALPHA[mode]});`];
|
|
3721
|
-
};
|
|
3722
3729
|
const outline = (mode) => {
|
|
3723
3730
|
if (secondaryStyle !== "outline" || !secondary) return [];
|
|
3724
3731
|
const s8 = (mode === "light" ? secondary.light : secondary.dark).find((s) => s.stop === 8);
|
|
@@ -3762,7 +3769,6 @@ function brandCss(slug, displayName, r, secondary, noteSuffix = "", neutralLevel
|
|
|
3762
3769
|
...linkInverse("light"),
|
|
3763
3770
|
brandIdentity,
|
|
3764
3771
|
...secondaryLight,
|
|
3765
|
-
...softOnCta("light"),
|
|
3766
3772
|
...outline("light"),
|
|
3767
3773
|
secondaryIdentity,
|
|
3768
3774
|
...brandKindBody(CSS_NEUTRAL, nScale, "light", page.light),
|
|
@@ -3775,7 +3781,6 @@ function brandCss(slug, displayName, r, secondary, noteSuffix = "", neutralLevel
|
|
|
3775
3781
|
...link("dark"),
|
|
3776
3782
|
...linkInverse("dark"),
|
|
3777
3783
|
...secondaryDark,
|
|
3778
|
-
...softOnCta("dark"),
|
|
3779
3784
|
...outline("dark"),
|
|
3780
3785
|
...brandKindBody(CSS_NEUTRAL, nScale, "dark", page.dark),
|
|
3781
3786
|
...effOverrides.flatMap((o) => brandKindBody(SIGNAL_EMIT_NAME[o.name], o.scale, "dark", page.dark)),
|
package/dist-lib/index.mjs
CHANGED
|
@@ -2638,6 +2638,12 @@ function generateScale(hex, scaleName, forcedArchetype, opts) {
|
|
|
2638
2638
|
pen100Dark: penPole(dark, 1)
|
|
2639
2639
|
};
|
|
2640
2640
|
}
|
|
2641
|
+
function neutralTintHue(primaryH, source, secondaryH, customHex) {
|
|
2642
|
+
if (source === "secondary" && secondaryH !== void 0) return secondaryH;
|
|
2643
|
+
if (source === "custom" && customHex && /^#?[0-9a-fA-F]{6}$/.test(customHex))
|
|
2644
|
+
return hexToOklch(customHex.startsWith("#") ? customHex : `#${customHex}`).H;
|
|
2645
|
+
return primaryH;
|
|
2646
|
+
}
|
|
2641
2647
|
function generateNeutralScale(brandH, level = "default", contrastProfile) {
|
|
2642
2648
|
const h = (brandH % 360 + 360) % 360;
|
|
2643
2649
|
const { r, g: g2, b } = oklchToSrgbUnclamped(0.5, 6e-3, h);
|
|
@@ -3443,9 +3449,12 @@ var SHADOW_ALPHAS = {
|
|
|
3443
3449
|
var SCRIM_ALPHA = 0.6;
|
|
3444
3450
|
var DISABLED_OPACITY = 0.38;
|
|
3445
3451
|
var TRANSPARENT_VAR = "--alpha-transparent";
|
|
3452
|
+
var SCRIM_VAR = "--abs-black-060";
|
|
3446
3453
|
var offsetRgba = (rung, mode) => mode === "light" ? `rgba(0, 0, 0, ${OFFSET_ALPHAS[rung]})` : `rgba(255, 255, 255, ${OFFSET_ALPHAS[rung]})`;
|
|
3447
3454
|
var alphaRootVars = (mode) => [
|
|
3448
3455
|
` ${TRANSPARENT_VAR}: transparent;`,
|
|
3456
|
+
// mode-invariant like transparent; repeated in the dark block to keep the set together
|
|
3457
|
+
` ${SCRIM_VAR}: rgba(0, 0, 0, ${SCRIM_ALPHA});`,
|
|
3449
3458
|
...Object.keys(OFFSET_ALPHAS).map(Number).sort((a, b) => a - b).map((r) => ` ${offsetVarName(r)}: ${offsetRgba(r, mode)};`),
|
|
3450
3459
|
// the toward-bg ladder (the 2026-08-29 inverse ladder, renamed 2026-08-31): the
|
|
3451
3460
|
// same rungs, pole flipped per mode — state layers for INVERTED grounds (never
|
|
@@ -3461,7 +3470,7 @@ function ctaNeedsBorder(s, mode, page) {
|
|
|
3461
3470
|
if (!page) return false;
|
|
3462
3471
|
return ctaPageLc(s, mode, page) < CTA_BORDER_LC_FLOOR;
|
|
3463
3472
|
}
|
|
3464
|
-
function brandKindBody(prefix, s, mode, page) {
|
|
3473
|
+
function brandKindBody(prefix, s, mode, page, on = prefix === CSS_NEUTRAL ? "soft" : "solid") {
|
|
3465
3474
|
const stops = mode === "light" ? s.light : s.dark;
|
|
3466
3475
|
const f = ctaFamilyOf(s, mode);
|
|
3467
3476
|
const onCta = mode === "light" ? s.onFillTextIsWhite : s.onFillTextIsWhiteDark;
|
|
@@ -3480,10 +3489,10 @@ function brandKindBody(prefix, s, mode, page) {
|
|
|
3480
3489
|
// button text takes the pole AT ALPHA like the default-model secondary's — composited
|
|
3481
3490
|
// over whatever state the fill is in, so hover/pressed carry their own legibility. Same
|
|
3482
3491
|
// register both families (SOFT_ON_CTA_ALPHA), so both alias the ONE system/alpha/ink
|
|
3483
|
-
// primitive.
|
|
3484
|
-
//
|
|
3485
|
-
//
|
|
3486
|
-
|
|
3492
|
+
// primitive. The neutral's is unconditional (the parameter default); the secondary's is
|
|
3493
|
+
// the caller's per-mode verdict. Loud fills (brand, signals, the cta escape) keep the
|
|
3494
|
+
// solid pole.
|
|
3495
|
+
on === "soft" ? ` --${prefix}-stamp-on: rgba(${onCta ? "255, 255, 255" : "0, 0, 0"}, ${SOFT_ON_CTA_ALPHA[mode]});` : ` --${prefix}-stamp-on: ${onColor(onCta)};`
|
|
3487
3496
|
];
|
|
3488
3497
|
}
|
|
3489
3498
|
function ctaFamilyOf(s, mode) {
|
|
@@ -3550,7 +3559,8 @@ function signalsCss(contrastProfile) {
|
|
|
3550
3559
|
// the system alpha variables every family's cta-border aliases (owner 2026-07-29) — this is
|
|
3551
3560
|
// the engine's one global :root, the CSS counterpart of the Figma side's system/alpha/* rows.
|
|
3552
3561
|
// Emitted in BOTH blocks because the offset rungs are scheme-DIVERGENT (black in light,
|
|
3553
|
-
// white in dark); --alpha-transparent
|
|
3562
|
+
// white in dark); --alpha-transparent and the scrim (both mode-invariant) repeat
|
|
3563
|
+
// harmlessly and keep the set together.
|
|
3554
3564
|
...alphaRootVars("light"),
|
|
3555
3565
|
...lightBlocks,
|
|
3556
3566
|
`}`,
|
|
@@ -3599,8 +3609,9 @@ function brandCss(slug, displayName, r, secondary, noteSuffix = "", neutralLevel
|
|
|
3599
3609
|
alias("stamp-on")
|
|
3600
3610
|
];
|
|
3601
3611
|
};
|
|
3602
|
-
const
|
|
3603
|
-
const
|
|
3612
|
+
const secondaryOn = (mode) => secondary && secondaryStyle !== "outline" && softOnCtaPasses(secondary, mode) ? "soft" : "solid";
|
|
3613
|
+
const secondaryLight = secondary ? brandKindBody(CSS_SECONDARY, secondary, "light", page.light, secondaryOn("light")) : mirrorBody(CSS_SECONDARY, "light");
|
|
3614
|
+
const secondaryDark = secondary ? brandKindBody(CSS_SECONDARY, secondary, "dark", page.dark, secondaryOn("dark")) : mirrorBody(CSS_SECONDARY, "dark");
|
|
3604
3615
|
const brandIdentity = ` --${CSS_BRAND}-identity: ${scale.identityHex};`;
|
|
3605
3616
|
const secondaryIdentity = secondary ? ` --${CSS_SECONDARY}-identity: ${secondary.identityHex};` : ` --${CSS_SECONDARY}-identity: var(--${CSS_BRAND}-identity);`;
|
|
3606
3617
|
const p0hex = (s, fallback) => s ? stopHex(s) : fallback;
|
|
@@ -3634,12 +3645,6 @@ function brandCss(slug, displayName, r, secondary, noteSuffix = "", neutralLevel
|
|
|
3634
3645
|
` --${CSS_BRAND}-stamp-on: ${onColor(esc.onFillIsWhite)};`
|
|
3635
3646
|
];
|
|
3636
3647
|
};
|
|
3637
|
-
const softOnCta = (mode) => {
|
|
3638
|
-
if (!secondary || secondaryStyle === "outline") return [];
|
|
3639
|
-
if (!softOnCtaPasses(secondary, mode)) return [];
|
|
3640
|
-
const white = mode === "light" ? secondary.onFillTextIsWhite : secondary.onFillTextIsWhiteDark;
|
|
3641
|
-
return [` --${CSS_SECONDARY}-stamp-on: rgba(${white ? "255, 255, 255" : "0, 0, 0"}, ${SOFT_ON_CTA_ALPHA[mode]});`];
|
|
3642
|
-
};
|
|
3643
3648
|
const outline = (mode) => {
|
|
3644
3649
|
if (secondaryStyle !== "outline" || !secondary) return [];
|
|
3645
3650
|
const s8 = (mode === "light" ? secondary.light : secondary.dark).find((s) => s.stop === 8);
|
|
@@ -3683,7 +3688,6 @@ function brandCss(slug, displayName, r, secondary, noteSuffix = "", neutralLevel
|
|
|
3683
3688
|
...linkInverse("light"),
|
|
3684
3689
|
brandIdentity,
|
|
3685
3690
|
...secondaryLight,
|
|
3686
|
-
...softOnCta("light"),
|
|
3687
3691
|
...outline("light"),
|
|
3688
3692
|
secondaryIdentity,
|
|
3689
3693
|
...brandKindBody(CSS_NEUTRAL, nScale, "light", page.light),
|
|
@@ -3696,7 +3700,6 @@ function brandCss(slug, displayName, r, secondary, noteSuffix = "", neutralLevel
|
|
|
3696
3700
|
...link("dark"),
|
|
3697
3701
|
...linkInverse("dark"),
|
|
3698
3702
|
...secondaryDark,
|
|
3699
|
-
...softOnCta("dark"),
|
|
3700
3703
|
...outline("dark"),
|
|
3701
3704
|
...brandKindBody(CSS_NEUTRAL, nScale, "dark", page.dark),
|
|
3702
3705
|
...effOverrides.flatMap((o) => brandKindBody(SIGNAL_EMIT_NAME[o.name], o.scale, "dark", page.dark)),
|
|
@@ -3976,6 +3979,7 @@ export {
|
|
|
3976
3979
|
RESOLVER_ID,
|
|
3977
3980
|
SCALE_STOP_COUNT,
|
|
3978
3981
|
SCRIM_ALPHA,
|
|
3982
|
+
SCRIM_VAR,
|
|
3979
3983
|
SECONDARY_DISTINCT_DELTA_E,
|
|
3980
3984
|
SHADOW_ALPHAS,
|
|
3981
3985
|
SIGNALS2 as SIGNALS,
|
|
@@ -4003,6 +4007,7 @@ export {
|
|
|
4003
4007
|
generateScale,
|
|
4004
4008
|
generateSubtleSecondary,
|
|
4005
4009
|
neutralCss,
|
|
4010
|
+
neutralTintHue,
|
|
4006
4011
|
pageStopFor,
|
|
4007
4012
|
parseToken,
|
|
4008
4013
|
resolveBrand,
|
|
@@ -35,11 +35,12 @@ export type ShadowRung = keyof typeof SHADOW_ALPHAS;
|
|
|
35
35
|
export declare const SCRIM_ALPHA = 0.6;
|
|
36
36
|
export declare const DISABLED_OPACITY = 0.38;
|
|
37
37
|
export declare const TRANSPARENT_VAR = "--alpha-transparent";
|
|
38
|
+
export declare const SCRIM_VAR = "--abs-black-060";
|
|
38
39
|
export declare const offsetRgba: (rung: OffsetRung, mode: "light" | "dark") => string;
|
|
39
40
|
export declare const alphaRootVars: (mode: "light" | "dark") => string[];
|
|
40
41
|
export declare function ctaPageLc(s: GeneratedScale, mode: 'light' | 'dark', page: ColorStop): number;
|
|
41
42
|
export declare function ctaNeedsBorder(s: GeneratedScale, mode: 'light' | 'dark', page: ColorStop | undefined): boolean;
|
|
42
|
-
export declare function brandKindBody(prefix: string, s: GeneratedScale, mode: 'light' | 'dark', page: ColorStop | undefined): string[];
|
|
43
|
+
export declare function brandKindBody(prefix: string, s: GeneratedScale, mode: 'light' | 'dark', page: ColorStop | undefined, on?: 'soft' | 'solid'): string[];
|
|
43
44
|
export declare function brandKindP3Body(prefix: string, s: GeneratedScale, mode: 'light' | 'dark'): string[];
|
|
44
45
|
export declare function neutralCss(selector: string, brandH: number, level?: NeutralLevel, contrastProfile?: ContrastProfile, ctaBorder?: boolean): string;
|
|
45
46
|
export declare function signalsCss(contrastProfile?: ContrastProfile): string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { generateScale, generateNeutralScale, generateSubtleSecondary, type GeneratedScale, type ColorStop, type GenerateOptions, type NeutralLevel, type ContrastProfile, } from './engine/colorEngine';
|
|
1
|
+
export { generateScale, generateNeutralScale, generateSubtleSecondary, neutralTintHue, type NeutralSource, type GeneratedScale, type ColorStop, type GenerateOptions, type NeutralLevel, type ContrastProfile, } from './engine/colorEngine';
|
|
2
2
|
export { resolveBrand, resolveTheme, resolveLinkTrio, resolveLinkInverseTrio, DEFAULT_LINK_HEX, SIGNAL_SCALES, signalScalesFor, SECONDARY_DISTINCT_DELTA_E, SUBTLE_TINT_MULT, SUBTLE_PASTEL_K, OUTLINE_HOVER_ALPHA, type ResolvedBrand, type ResolvedTheme, type ResolvedSecondary, type SecondaryLevel, type SecondaryStyle, type SignalOverride, } from './engine/resolve';
|
|
3
|
-
export { brandCss, neutralCss, signalsCss, stopsToVars, toHex, stopHex, OFFSET_ALPHAS, SHADOW_ALPHAS, SCRIM_ALPHA, DISABLED_OPACITY, type ShadowRung, ctaNeedsBorder, ctaBorderRung, pageStopFor, } from './engine/cssRender';
|
|
3
|
+
export { brandCss, neutralCss, signalsCss, stopsToVars, toHex, stopHex, OFFSET_ALPHAS, SHADOW_ALPHAS, SCRIM_ALPHA, SCRIM_VAR, DISABLED_OPACITY, type ShadowRung, ctaNeedsBorder, ctaBorderRung, pageStopFor, } from './engine/cssRender';
|
|
4
4
|
export { CSS_FAMILY } from './engine/tokenDescriptions';
|
|
5
5
|
export { themeToFigma, type FigmaGroup, type FigmaColorToken, type ThemeInput, } from './engine/figmaRender';
|
|
6
6
|
export { emitDtcgRamp, resolveDtcgRamp, parseToken, EXT_KEY, RESOLVER_ID, type DtcgRampGroup, type DtcgRequirementToken, type DtcgSeedToken, type DtcgColorValue, } from './engine/requirements/dtcg';
|
package/package.json
CHANGED
package/tokens/semantic.css
CHANGED
|
@@ -1,20 +1,18 @@
|
|
|
1
1
|
/*
|
|
2
|
-
Semantic token layer
|
|
2
|
+
Semantic token layer: maps role names to primitive tokens.
|
|
3
3
|
This file never changes per brand. Only the primitives (--brand-*, --neutral-*) change.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
/* ─── Global surface / fg / border ─────────────────────────────────────────── */
|
|
7
7
|
|
|
8
8
|
[data-brand] {
|
|
9
|
-
/* Elevation planes
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
paper-0
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
always the extreme pole: the high in light, the sunken in dark. The stops
|
|
17
|
-
themselves have never moved through any of the renames. */
|
|
9
|
+
/* Elevation planes dim, low, mid, high: mid is the raised plane components sit on,
|
|
10
|
+
the page behind it is low, and the two extremes are edge cases. Both themes use
|
|
11
|
+
the SAME four stops in reversed order, so elevation always moves toward paper-0's
|
|
12
|
+
side of the ramp. Light descends the ramp as elevation rises (dim paper-5 to high
|
|
13
|
+
paper-0, white); dark ascends it (dim paper-0, the deep tinted ground, to high
|
|
14
|
+
paper-5). paper-0 flips with the mode, so it is always the extreme pole: the high
|
|
15
|
+
in light, the dim in dark. */
|
|
18
16
|
--surface-dim: var(--neutral-paper-5);
|
|
19
17
|
--surface-low: var(--neutral-paper-3);
|
|
20
18
|
--surface-mid: var(--neutral-paper-1);
|
|
@@ -22,41 +20,40 @@
|
|
|
22
20
|
|
|
23
21
|
--fg-default: var(--neutral-pen-70);
|
|
24
22
|
--fg-subtle: var(--neutral-pencil-47);
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
carries the WCAG 1.4.11 3:1 non-text require (highlight-8 pre-Stage-B). It sat on
|
|
31
|
-
--neutral-highlight-9 until that stop was deleted; crayon-26 is where the
|
|
32
|
-
requirement actually lives, and it is the one stop this round does not move.
|
|
33
|
-
Decorative borders are --border-subtle (highlighter-11) and the per-family
|
|
34
|
-
--*-border-default (highlighter-15). */
|
|
23
|
+
|
|
24
|
+
/* --border-default IS THE ACCESSIBILITY BORDER: a border that has to be there (inputs
|
|
25
|
+
and other controls), so it rides crayon-26, the stop that carries the 3:1 non-text
|
|
26
|
+
contrast requirement. Decorative borders are --border-subtle (highlighter-11) and
|
|
27
|
+
the per-family --*-border-default (highlighter-15). */
|
|
35
28
|
--border-default: var(--neutral-crayon-26);
|
|
36
29
|
--border-subtle: var(--neutral-highlighter-11);
|
|
37
30
|
|
|
38
|
-
/* Shadow transparencies
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
31
|
+
/* Shadow transparencies: pure black, the engine's SHADOW_ALPHAS, the same rows the
|
|
32
|
+
plugins write as shadow-04|08|12. Dark is heavier by necessity: near black a
|
|
33
|
+
light-mode alpha vanishes, so the dark values carry the same roles at heavier
|
|
34
|
+
alphas. Elevation recipes compose these, so dark shadows fall out of the token
|
|
35
|
+
swap with nothing bespoke per style. */
|
|
43
36
|
--shadow-04: rgba(0, 0, 0, 0.04);
|
|
44
37
|
--shadow-08: rgba(0, 0, 0, 0.08);
|
|
45
38
|
--shadow-12: rgba(0, 0, 0, 0.12);
|
|
46
39
|
|
|
47
|
-
/*
|
|
48
|
-
|
|
49
|
-
|
|
40
|
+
/* The scrim: the modal veil, black at 60% in both modes. The primitive
|
|
41
|
+
(--abs-black-060) rides signalsCss's :root, the same row the plugins write
|
|
42
|
+
as abs-black-060; this alias is the job word. */
|
|
43
|
+
--scrim: var(--abs-black-060);
|
|
44
|
+
|
|
45
|
+
/* Disabled opacity: disabled is a COMPONENT-LEVEL opacity. Colors stay the enabled
|
|
46
|
+
ones and never swap. Mode-invariant; mirrors the JS API's DISABLED_OPACITY
|
|
47
|
+
constant 1:1. */
|
|
50
48
|
--disabled-opacity: 0.38;
|
|
51
49
|
}
|
|
52
50
|
|
|
53
51
|
[data-brand][data-theme="dark"] {
|
|
54
|
-
/* Dark runs the same four stops upward:
|
|
55
|
-
|
|
52
|
+
/* Dark runs the same four stops upward: dim paper-0 (the deep tinted ground), low
|
|
53
|
+
paper-1, mid paper-3, high paper-5, the one-level highest background: every
|
|
56
54
|
family's paper-5 shares one photometric level, so chips sit flush on the high
|
|
57
|
-
plane by construction
|
|
58
|
-
|
|
59
|
-
low is paper-3 (the light value); the stops themselves did not move. */
|
|
55
|
+
plane by construction. Low needs its own override here because the shared
|
|
56
|
+
block's low is paper-3, the light value. */
|
|
60
57
|
--surface-dim: var(--paper-0, #000000);
|
|
61
58
|
--surface-low: var(--neutral-paper-1);
|
|
62
59
|
--surface-mid: var(--neutral-paper-3);
|
|
@@ -90,15 +87,15 @@
|
|
|
90
87
|
--brand-border-emphasis: var(--brand-stamp-fill);
|
|
91
88
|
--brand-border-emphasis-hover: var(--brand-stamp-fill-hover);
|
|
92
89
|
|
|
93
|
-
/* the SYSTEM LINK (one trio per theme
|
|
90
|
+
/* the SYSTEM LINK (one trio per theme; aliases the primary's pen stops unless a custom
|
|
94
91
|
link color de-conflicts it; --link/-hover/-pressed are emitted per brand) */
|
|
95
92
|
--fg-link: var(--link);
|
|
96
93
|
--fg-link-hover: var(--link-hover);
|
|
97
94
|
--fg-link-pressed: var(--link-pressed);
|
|
98
95
|
|
|
99
|
-
/* the INVERSE link trio
|
|
100
|
-
|
|
101
|
-
|
|
96
|
+
/* the INVERSE link trio: the same link seed re-solved for text on inverted surfaces
|
|
97
|
+
(a pen-70 fill); always its own emitted values, since no stop is anchored against
|
|
98
|
+
that ground and so there is no alias posture */
|
|
102
99
|
--fg-link-inverse: var(--link-inverse);
|
|
103
100
|
--fg-link-inverse-hover: var(--link-inverse-hover);
|
|
104
101
|
--fg-link-inverse-pressed: var(--link-inverse-pressed);
|
|
@@ -131,20 +128,15 @@
|
|
|
131
128
|
/* ─── Signal roles ──────────────────────────────────────────────────────────
|
|
132
129
|
Aliases onto engine-generated signal primitives (dist/signals.css).
|
|
133
130
|
Mode switching happens at the primitive layer, so one block covers both.
|
|
134
|
-
Signal families emit by ROLE (
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
it clears 4.5 against pencil-47 everywhere (agnostic 360-seed sweep, worst 4.96
|
|
144
|
-
light / 8.04 dark). -bg-emphasis / -border-emphasis moved from highlight-9 to
|
|
145
|
-
pencil-47 (ink-9 pre-Stage-B) with it; in dark that reads lighter (contrast vs
|
|
146
|
-
paper-5, median 6.01 → 7.72). Stage B (owner 2026-08-07, names only) relabeled
|
|
147
|
-
every leaf in the block below; the stops themselves did not move. */
|
|
131
|
+
Signal families emit by ROLE (critical/warning/positive/info, the re-pointable
|
|
132
|
+
in-between tier; identity stays engine-internal), so the role tokens and the
|
|
133
|
+
family ramp share a prefix: --critical-fg rides --critical-pen-70.
|
|
134
|
+
|
|
135
|
+
-fg-on-emphasis rides --paper-0, NOT a solved on-color. paper-0 is the
|
|
136
|
+
mode-flipping paper extreme (white in light, the deep tinted ground in dark) and
|
|
137
|
+
it clears the 4.5:1 text bar against pencil-47 in every family and both modes;
|
|
138
|
+
the band audit holds that floor over an agnostic sweep. -bg-emphasis and
|
|
139
|
+
-border-emphasis ride pencil-47. */
|
|
148
140
|
|
|
149
141
|
[data-brand] {
|
|
150
142
|
--critical-fg: var(--critical-pen-70);
|