@handamade/psi-tokens 0.19.0 → 0.21.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 +19 -0
- package/dist/base.css +3 -0
- package/dist/cli/psi-theme.d.ts +2 -0
- package/dist/cli/psi-theme.js +56 -0
- package/dist/components/app-shell.d.ts +16 -0
- package/dist/components/app-shell.js +21 -0
- package/dist/components/app-shell.vars.css +8 -0
- package/dist/components/banner.d.ts +11 -0
- package/dist/components/banner.js +21 -0
- package/dist/components/banner.vars.css +13 -0
- package/dist/components/button.d.ts +7 -0
- package/dist/components/button.js +76 -0
- package/dist/components/card.d.ts +2 -0
- package/dist/components/card.js +7 -0
- package/dist/components/checkbox.d.ts +2 -0
- package/dist/components/checkbox.js +13 -0
- package/dist/components/control.d.ts +21 -0
- package/dist/components/control.js +59 -0
- package/dist/components/description-list.d.ts +8 -0
- package/dist/components/description-list.js +13 -0
- package/dist/components/dialog.d.ts +6 -0
- package/dist/components/dialog.js +16 -0
- package/dist/components/dialog.vars.css +1 -0
- package/dist/components/field.d.ts +3 -0
- package/dist/components/field.js +14 -0
- package/dist/components/field.vars.css +1 -0
- package/dist/components/inline-alert.d.ts +12 -0
- package/dist/components/inline-alert.js +27 -0
- package/dist/components/inline-alert.vars.css +18 -0
- package/dist/components/input.d.ts +2 -0
- package/dist/components/input.js +25 -0
- package/dist/components/media.d.ts +3 -0
- package/dist/components/media.js +5 -0
- package/dist/components/menu.d.ts +7 -0
- package/dist/components/menu.js +21 -0
- package/dist/components/menu.vars.css +1 -0
- package/dist/components/nav-tree.d.ts +12 -0
- package/dist/components/nav-tree.js +26 -0
- package/dist/components/nav-tree.vars.css +12 -0
- package/dist/components/navbar.d.ts +3 -0
- package/dist/components/navbar.js +14 -0
- package/dist/components/navbar.vars.css +1 -0
- package/dist/components/navtree.d.ts +12 -0
- package/dist/components/navtree.js +26 -0
- package/dist/components/navtree.vars.css +12 -0
- package/dist/components/panel.d.ts +5 -0
- package/dist/components/panel.js +10 -0
- package/dist/components/registry.d.ts +1 -0
- package/dist/components/registry.js +58 -0
- package/dist/components/select.d.ts +2 -0
- package/dist/components/select.js +38 -0
- package/dist/components/skeleton.d.ts +4 -0
- package/dist/components/skeleton.js +7 -0
- package/dist/components/skeleton.vars.css +6 -0
- package/dist/components/skip-link.d.ts +6 -0
- package/dist/components/skip-link.js +12 -0
- package/dist/components/skip-link.vars.css +9 -0
- package/dist/components/skiplink.d.ts +6 -0
- package/dist/components/skiplink.js +12 -0
- package/dist/components/skiplink.vars.css +9 -0
- package/dist/components/surface.d.ts +5 -0
- package/dist/components/surface.js +10 -0
- package/dist/components/switch.d.ts +2 -0
- package/dist/components/switch.js +8 -0
- package/dist/components/table.d.ts +12 -0
- package/dist/components/table.js +30 -0
- package/dist/components/tabs.d.ts +14 -0
- package/dist/components/tabs.js +26 -0
- package/dist/components/tag.d.ts +4 -0
- package/dist/components/tag.js +26 -0
- package/dist/components/toast.d.ts +19 -0
- package/dist/components/toast.js +28 -0
- package/dist/components/toolbar.d.ts +13 -0
- package/dist/components/toolbar.js +15 -0
- package/dist/components/tooltip.d.ts +2 -0
- package/dist/components/tooltip.js +7 -0
- package/dist/components.css +76 -0
- package/dist/contrast-matrix.js +8 -0
- package/dist/dsl/validator.d.ts +12 -0
- package/dist/dsl/validator.js +97 -0
- package/dist/dtcg/acme.json +18 -2
- package/dist/dtcg/dark.json +18 -2
- package/dist/dtcg/ember.json +18 -2
- package/dist/dtcg/light.json +18 -2
- package/dist/emit/css.d.ts +30 -0
- package/dist/emit/css.js +120 -0
- package/dist/gamut.d.ts +4 -0
- package/dist/gamut.js +44 -0
- package/dist/guidance.json +2 -2
- package/dist/resolved/acme.json +9 -2
- package/dist/resolved/dark.json +9 -2
- package/dist/resolved/ember.json +9 -2
- package/dist/resolved/light.json +9 -2
- package/dist/scope-gate.d.ts +15 -0
- package/dist/scope-gate.js +87 -0
- package/dist/scope-map.json +108 -3
- package/dist/scopes.d.ts +6 -0
- package/dist/scopes.js +88 -0
- package/dist/theme/gate.d.ts +19 -0
- package/dist/theme/gate.js +44 -0
- package/dist/theme/index.d.ts +16 -0
- package/dist/theme/index.js +23 -0
- package/dist/themes/dark.js +2 -2
- package/dist/themes/light.js +4 -2
- package/llms.txt +12 -0
- package/package.json +9 -1
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** NavTree component tokens (--psi-nav-tree-*) — D88. Pure indirection onto the
|
|
2
|
+
* semantic layer (same posture as menu.ts and tabs.ts), so every key resolves
|
|
3
|
+
* under a `data-psi-theme="dark"` sidebar inside a light page: component
|
|
4
|
+
* tokens are declared under `:where(:root, [data-psi-theme])`.
|
|
5
|
+
*
|
|
6
|
+
* No new contrast pairs: wcagAAPairs already gates fgPrimary and fgSecondary
|
|
7
|
+
* on bgPrimary and on fillNeutral1-6 in every theme, dark included, which
|
|
8
|
+
* covers the item text on the sidebar, on the hover surface (neutral3) and on
|
|
9
|
+
* the current surface (neutral4). `indicator` and `focus-ring` are non-text
|
|
10
|
+
* accents and `radius` is geometry; none carries a gated pair, so the pinned
|
|
11
|
+
* pair count does not move. */
|
|
12
|
+
export declare const navTreeVars: Record<string, string>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** NavTree component tokens (--psi-nav-tree-*) — D88. Pure indirection onto the
|
|
2
|
+
* semantic layer (same posture as menu.ts and tabs.ts), so every key resolves
|
|
3
|
+
* under a `data-psi-theme="dark"` sidebar inside a light page: component
|
|
4
|
+
* tokens are declared under `:where(:root, [data-psi-theme])`.
|
|
5
|
+
*
|
|
6
|
+
* No new contrast pairs: wcagAAPairs already gates fgPrimary and fgSecondary
|
|
7
|
+
* on bgPrimary and on fillNeutral1-6 in every theme, dark included, which
|
|
8
|
+
* covers the item text on the sidebar, on the hover surface (neutral3) and on
|
|
9
|
+
* the current surface (neutral4). `indicator` and `focus-ring` are non-text
|
|
10
|
+
* accents and `radius` is geometry; none carries a gated pair, so the pinned
|
|
11
|
+
* pair count does not move. */
|
|
12
|
+
export const navTreeVars = {
|
|
13
|
+
"item-fg": "var(--psi-fg-secondary)",
|
|
14
|
+
"item-fg-current": "var(--psi-fg-primary)",
|
|
15
|
+
"item-bg-hover": "var(--psi-fill-neutral3)",
|
|
16
|
+
"item-bg-current": "var(--psi-fill-neutral4)",
|
|
17
|
+
// The inline-start bar on the current item: weight and surface carry the
|
|
18
|
+
// state too, so colour is never the only signal.
|
|
19
|
+
indicator: "var(--psi-fill-accent)",
|
|
20
|
+
// A group's button reads like its items, one step quieter than the current.
|
|
21
|
+
"group-fg": "var(--psi-fg-secondary)",
|
|
22
|
+
// Alias of the control radius dial: a CSS Module may bind only its own
|
|
23
|
+
// component prefix, and the radius lives outside it.
|
|
24
|
+
radius: "var(--psi-control-radius)",
|
|
25
|
+
"focus-ring": "var(--psi-border-focus)",
|
|
26
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
@layer psi.components {
|
|
2
|
+
:where(:root, [data-psi-theme]) {
|
|
3
|
+
--psi-nav-tree-item-fg: var(--psi-fg-secondary);
|
|
4
|
+
--psi-nav-tree-item-fg-current: var(--psi-fg-primary);
|
|
5
|
+
--psi-nav-tree-item-bg-hover: var(--psi-fill-neutral3);
|
|
6
|
+
--psi-nav-tree-item-bg-current: var(--psi-fill-neutral4);
|
|
7
|
+
--psi-nav-tree-indicator: var(--psi-fill-accent);
|
|
8
|
+
--psi-nav-tree-group-fg: var(--psi-fg-secondary);
|
|
9
|
+
--psi-nav-tree-radius: var(--psi-control-radius);
|
|
10
|
+
--psi-nav-tree-focus-ring: var(--psi-border-focus);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** NavBar component tokens (--psi-navbar-*). bg defaults to the heavy scrim
|
|
2
|
+
* (page canvas @ 0.82) — the blur-backed sticky-header treatment. */
|
|
3
|
+
export const navbarVars = {
|
|
4
|
+
height: "4rem",
|
|
5
|
+
bg: "var(--psi-scrim-heavy)",
|
|
6
|
+
blur: "12px",
|
|
7
|
+
border: "var(--psi-border-faint)",
|
|
8
|
+
"link-fg": "var(--psi-fg-secondary)",
|
|
9
|
+
"link-fg-hover": "var(--psi-fg-primary)",
|
|
10
|
+
"focus-ring": "var(--psi-border-focus)",
|
|
11
|
+
// D88 — the side padding of a fluid row; the same gutter .psi-container pads
|
|
12
|
+
// with, reachable from the CSS Module only through a navbar token.
|
|
13
|
+
gutter: "var(--psi-gutter)",
|
|
14
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** NavTree component tokens (--psi-navtree-*) — D88. Pure indirection onto the
|
|
2
|
+
* semantic layer (same posture as menu.ts and tabs.ts), so every key resolves
|
|
3
|
+
* under a `data-psi-theme="dark"` sidebar inside a light page: component
|
|
4
|
+
* tokens are declared under `:where(:root, [data-psi-theme])`.
|
|
5
|
+
*
|
|
6
|
+
* No new contrast pairs: wcagAAPairs already gates fgPrimary and fgSecondary
|
|
7
|
+
* on bgPrimary and on fillNeutral1-6 in every theme, dark included, which
|
|
8
|
+
* covers the item text on the sidebar, on the hover surface (neutral3) and on
|
|
9
|
+
* the current surface (neutral4). `indicator` and `focus-ring` are non-text
|
|
10
|
+
* accents and `radius` is geometry; none carries a gated pair, so the pinned
|
|
11
|
+
* pair count does not move. */
|
|
12
|
+
export declare const navtreeVars: Record<string, string>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** NavTree component tokens (--psi-navtree-*) — D88. Pure indirection onto the
|
|
2
|
+
* semantic layer (same posture as menu.ts and tabs.ts), so every key resolves
|
|
3
|
+
* under a `data-psi-theme="dark"` sidebar inside a light page: component
|
|
4
|
+
* tokens are declared under `:where(:root, [data-psi-theme])`.
|
|
5
|
+
*
|
|
6
|
+
* No new contrast pairs: wcagAAPairs already gates fgPrimary and fgSecondary
|
|
7
|
+
* on bgPrimary and on fillNeutral1-6 in every theme, dark included, which
|
|
8
|
+
* covers the item text on the sidebar, on the hover surface (neutral3) and on
|
|
9
|
+
* the current surface (neutral4). `indicator` and `focus-ring` are non-text
|
|
10
|
+
* accents and `radius` is geometry; none carries a gated pair, so the pinned
|
|
11
|
+
* pair count does not move. */
|
|
12
|
+
export const navtreeVars = {
|
|
13
|
+
"item-fg": "var(--psi-fg-secondary)",
|
|
14
|
+
"item-fg-current": "var(--psi-fg-primary)",
|
|
15
|
+
"item-bg-hover": "var(--psi-fill-neutral3)",
|
|
16
|
+
"item-bg-current": "var(--psi-fill-neutral4)",
|
|
17
|
+
// The inline-start bar on the current item: weight and surface carry the
|
|
18
|
+
// state too, so colour is never the only signal.
|
|
19
|
+
indicator: "var(--psi-fill-accent)",
|
|
20
|
+
// A group's button reads like its items, one step quieter than the current.
|
|
21
|
+
"group-fg": "var(--psi-fg-secondary)",
|
|
22
|
+
// Alias of the control radius dial: a CSS Module may bind only its own
|
|
23
|
+
// component prefix, and the radius lives outside it.
|
|
24
|
+
radius: "var(--psi-control-radius)",
|
|
25
|
+
"focus-ring": "var(--psi-border-focus)",
|
|
26
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
@layer psi.components {
|
|
2
|
+
:where(:root, [data-psi-theme]) {
|
|
3
|
+
--psi-navtree-item-fg: var(--psi-fg-secondary);
|
|
4
|
+
--psi-navtree-item-fg-current: var(--psi-fg-primary);
|
|
5
|
+
--psi-navtree-item-bg-hover: var(--psi-fill-neutral3);
|
|
6
|
+
--psi-navtree-item-bg-current: var(--psi-fill-neutral4);
|
|
7
|
+
--psi-navtree-indicator: var(--psi-fill-accent);
|
|
8
|
+
--psi-navtree-group-fg: var(--psi-fg-secondary);
|
|
9
|
+
--psi-navtree-radius: var(--psi-control-radius);
|
|
10
|
+
--psi-navtree-focus-ring: var(--psi-border-focus);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Panel component tokens (--psi-panel-*) — D51. Pure indirection onto the
|
|
2
|
+
* shared surface family; exists because component CSS may only bind its own
|
|
3
|
+
* family (psi/component-tokens-only). Brands retune panels and dialogs
|
|
4
|
+
* together by overriding --psi-surface-*. */
|
|
5
|
+
export declare const panelVars: Record<string, string>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Panel component tokens (--psi-panel-*) — D51. Pure indirection onto the
|
|
2
|
+
* shared surface family; exists because component CSS may only bind its own
|
|
3
|
+
* family (psi/component-tokens-only). Brands retune panels and dialogs
|
|
4
|
+
* together by overriding --psi-surface-*. */
|
|
5
|
+
export const panelVars = {
|
|
6
|
+
bg: "var(--psi-surface-bg)",
|
|
7
|
+
border: "var(--psi-surface-border)",
|
|
8
|
+
radius: "var(--psi-surface-radius)",
|
|
9
|
+
padding: "var(--psi-surface-padding)",
|
|
10
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const componentVars: Record<string, Record<string, string>>;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// Component var registry (D81: moved out of scripts/build.ts) — the D46 scope
|
|
2
|
+
// gate reads it, in Psi's own build and in a consumer's theme build alike.
|
|
3
|
+
import { bannerVars } from "./banner.js";
|
|
4
|
+
import { inlineAlertVars } from "./inline-alert.js";
|
|
5
|
+
import { buttonVars } from "./button.js";
|
|
6
|
+
import { skeletonVars } from "./skeleton.js";
|
|
7
|
+
import { skipLinkVars } from "./skip-link.js";
|
|
8
|
+
import { navTreeVars } from "./nav-tree.js";
|
|
9
|
+
import { appShellVars } from "./app-shell.js";
|
|
10
|
+
import { inputVars } from "./input.js";
|
|
11
|
+
import { selectVars } from "./select.js";
|
|
12
|
+
import { surfaceVars } from "./surface.js";
|
|
13
|
+
import { checkboxVars } from "./checkbox.js";
|
|
14
|
+
import { switchVars } from "./switch.js";
|
|
15
|
+
import { tableVars } from "./table.js";
|
|
16
|
+
import { tagVars } from "./tag.js";
|
|
17
|
+
import { toolbarVars } from "./toolbar.js";
|
|
18
|
+
import { tooltipVars } from "./tooltip.js";
|
|
19
|
+
import { cardVars } from "./card.js";
|
|
20
|
+
import { controlVars } from "./control.js";
|
|
21
|
+
import { dialogVars } from "./dialog.js";
|
|
22
|
+
import { navbarVars } from "./navbar.js";
|
|
23
|
+
import { panelVars } from "./panel.js";
|
|
24
|
+
import { mediaVars } from "./media.js";
|
|
25
|
+
import { menuVars } from "./menu.js";
|
|
26
|
+
import { toastVars } from "./toast.js";
|
|
27
|
+
import { tabsVars } from "./tabs.js";
|
|
28
|
+
import { fieldVars } from "./field.js";
|
|
29
|
+
import { descriptionListVars } from "./description-list.js";
|
|
30
|
+
export const componentVars = {
|
|
31
|
+
"app-shell": appShellVars,
|
|
32
|
+
banner: bannerVars,
|
|
33
|
+
button: buttonVars,
|
|
34
|
+
card: cardVars,
|
|
35
|
+
checkbox: checkboxVars,
|
|
36
|
+
control: controlVars,
|
|
37
|
+
dialog: dialogVars,
|
|
38
|
+
field: fieldVars,
|
|
39
|
+
input: inputVars,
|
|
40
|
+
"inline-alert": inlineAlertVars,
|
|
41
|
+
media: mediaVars,
|
|
42
|
+
menu: menuVars,
|
|
43
|
+
navbar: navbarVars,
|
|
44
|
+
panel: panelVars,
|
|
45
|
+
select: selectVars,
|
|
46
|
+
skeleton: skeletonVars,
|
|
47
|
+
"nav-tree": navTreeVars,
|
|
48
|
+
"skip-link": skipLinkVars,
|
|
49
|
+
surface: surfaceVars,
|
|
50
|
+
switch: switchVars,
|
|
51
|
+
table: tableVars,
|
|
52
|
+
tabs: tabsVars,
|
|
53
|
+
"description-list": descriptionListVars,
|
|
54
|
+
tag: tagVars,
|
|
55
|
+
toolbar: toolbarVars,
|
|
56
|
+
toast: toastVars,
|
|
57
|
+
tooltip: tooltipVars,
|
|
58
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/** Select component tokens (--psi-select-*). */
|
|
2
|
+
export const selectVars = {
|
|
3
|
+
bg: "var(--psi-bg-primary)",
|
|
4
|
+
fg: "var(--psi-fg-primary)",
|
|
5
|
+
placeholder: "var(--psi-fg-tertiary)",
|
|
6
|
+
border: "var(--psi-border-neutral)",
|
|
7
|
+
"border-hover": "var(--psi-border-strong)",
|
|
8
|
+
"border-error": "var(--psi-fg-danger)",
|
|
9
|
+
"focus-ring": "var(--psi-border-focus)",
|
|
10
|
+
"chevron-fg": "var(--psi-fg-secondary)",
|
|
11
|
+
// ── Shape (D56) ──
|
|
12
|
+
radius: "var(--psi-control-radius)",
|
|
13
|
+
// ── Size ramp (D54) — same value ramp as Input, by construction ──
|
|
14
|
+
"24-height": "var(--psi-control-24-height)",
|
|
15
|
+
"32-height": "var(--psi-control-32-height)",
|
|
16
|
+
"40-height": "var(--psi-control-40-height)",
|
|
17
|
+
"48-height": "var(--psi-control-48-height)",
|
|
18
|
+
"24-padding-inline": "var(--psi-control-value-24-padding-inline)",
|
|
19
|
+
"32-padding-inline": "var(--psi-control-value-32-padding-inline)",
|
|
20
|
+
"40-padding-inline": "var(--psi-control-value-40-padding-inline)",
|
|
21
|
+
"48-padding-inline": "var(--psi-control-value-48-padding-inline)",
|
|
22
|
+
"24-font": "var(--psi-control-value-24-font)",
|
|
23
|
+
"32-font": "var(--psi-control-value-32-font)",
|
|
24
|
+
"40-font": "var(--psi-control-value-40-font)",
|
|
25
|
+
"48-font": "var(--psi-control-value-48-font)",
|
|
26
|
+
// Chevron well: the glyph is two 4px gradient strokes centred in a 12px well
|
|
27
|
+
// (D81 — it was a 12x12 data URI, which a strict CSP blocks), so the end padding is
|
|
28
|
+
// offset + 12 + 4 breathing = offset + 16. 28px is not on the spacing
|
|
29
|
+
// scale, so the +16 is expressed as calc rather than a scale step.
|
|
30
|
+
"24-chevron-offset": "var(--psi-control-value-24-padding-inline)",
|
|
31
|
+
"32-chevron-offset": "var(--psi-control-value-32-padding-inline)",
|
|
32
|
+
"40-chevron-offset": "var(--psi-control-value-40-padding-inline)",
|
|
33
|
+
"48-chevron-offset": "var(--psi-control-value-48-padding-inline)",
|
|
34
|
+
"24-padding-inline-end": "calc(var(--psi-control-value-24-padding-inline) + var(--psi-space-16))",
|
|
35
|
+
"32-padding-inline-end": "calc(var(--psi-control-value-32-padding-inline) + var(--psi-space-16))",
|
|
36
|
+
"40-padding-inline-end": "calc(var(--psi-control-value-40-padding-inline) + var(--psi-space-16))",
|
|
37
|
+
"48-padding-inline-end": "calc(var(--psi-control-value-48-padding-inline) + var(--psi-space-16))",
|
|
38
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Skeleton component tokens (--psi-skeleton-*) — D86. Pure indirection, same
|
|
2
|
+
* posture as banner.ts. A placeholder carries no text, so there is no
|
|
3
|
+
* foreground pair to gate; it is a quiet neutral shape. */
|
|
4
|
+
export const skeletonVars = {
|
|
5
|
+
bg: "var(--psi-fill-neutral4)",
|
|
6
|
+
radius: "var(--psi-radius-4)",
|
|
7
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** SkipLink component tokens (--psi-skip-link-*) — D88. Pure indirection onto
|
|
2
|
+
* the shared surface and focus tokens (same posture as menu.ts and
|
|
3
|
+
* navbar.ts): the link shows only when focused, on a surface, so a brand
|
|
4
|
+
* retuning --psi-surface-* gets it for free. radius rides the control radius
|
|
5
|
+
* dial, as Button's does, so the link matches the controls around it. */
|
|
6
|
+
export declare const skipLinkVars: Record<string, string>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** SkipLink component tokens (--psi-skip-link-*) — D88. Pure indirection onto
|
|
2
|
+
* the shared surface and focus tokens (same posture as menu.ts and
|
|
3
|
+
* navbar.ts): the link shows only when focused, on a surface, so a brand
|
|
4
|
+
* retuning --psi-surface-* gets it for free. radius rides the control radius
|
|
5
|
+
* dial, as Button's does, so the link matches the controls around it. */
|
|
6
|
+
export const skipLinkVars = {
|
|
7
|
+
bg: "var(--psi-surface-bg)",
|
|
8
|
+
fg: "var(--psi-fg-primary)",
|
|
9
|
+
border: "var(--psi-surface-border)",
|
|
10
|
+
radius: "var(--psi-control-radius)",
|
|
11
|
+
"focus-ring": "var(--psi-border-focus)",
|
|
12
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
@layer psi.components {
|
|
2
|
+
:where(:root, [data-psi-theme]) {
|
|
3
|
+
--psi-skip-link-bg: var(--psi-surface-bg);
|
|
4
|
+
--psi-skip-link-fg: var(--psi-fg-primary);
|
|
5
|
+
--psi-skip-link-border: var(--psi-surface-border);
|
|
6
|
+
--psi-skip-link-radius: var(--psi-control-radius);
|
|
7
|
+
--psi-skip-link-focus-ring: var(--psi-border-focus);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** SkipLink component tokens (--psi-skiplink-*) — D88. Pure indirection onto
|
|
2
|
+
* the shared surface and focus tokens (same posture as menu.ts and
|
|
3
|
+
* navbar.ts): the link shows only when focused, on a surface, so a brand
|
|
4
|
+
* retuning --psi-surface-* gets it for free. radius rides the control radius
|
|
5
|
+
* dial, as Button's does, so the link matches the controls around it. */
|
|
6
|
+
export declare const skiplinkVars: Record<string, string>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** SkipLink component tokens (--psi-skiplink-*) — D88. Pure indirection onto
|
|
2
|
+
* the shared surface and focus tokens (same posture as menu.ts and
|
|
3
|
+
* navbar.ts): the link shows only when focused, on a surface, so a brand
|
|
4
|
+
* retuning --psi-surface-* gets it for free. radius rides the control radius
|
|
5
|
+
* dial, as Button's does, so the link matches the controls around it. */
|
|
6
|
+
export const skiplinkVars = {
|
|
7
|
+
bg: "var(--psi-surface-bg)",
|
|
8
|
+
fg: "var(--psi-fg-primary)",
|
|
9
|
+
border: "var(--psi-surface-border)",
|
|
10
|
+
radius: "var(--psi-control-radius)",
|
|
11
|
+
"focus-ring": "var(--psi-border-focus)",
|
|
12
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
@layer psi.components {
|
|
2
|
+
:where(:root, [data-psi-theme]) {
|
|
3
|
+
--psi-skiplink-bg: var(--psi-surface-bg);
|
|
4
|
+
--psi-skiplink-fg: var(--psi-fg-primary);
|
|
5
|
+
--psi-skiplink-border: var(--psi-surface-border);
|
|
6
|
+
--psi-skiplink-radius: var(--psi-control-radius);
|
|
7
|
+
--psi-skiplink-focus-ring: var(--psi-border-focus);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Shared elevated-surface tokens (--psi-surface-*) — D51. The recipe two
|
|
2
|
+
* consumers converged on independently (Dialog's panel, promo's hand-rolled
|
|
3
|
+
* .card): secondary background, faint hairline, radius-12, space-24
|
|
4
|
+
* padding. Dialog and Panel bind these; there is no Surface component. */
|
|
5
|
+
export declare const surfaceVars: Record<string, string>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Shared elevated-surface tokens (--psi-surface-*) — D51. The recipe two
|
|
2
|
+
* consumers converged on independently (Dialog's panel, promo's hand-rolled
|
|
3
|
+
* .card): secondary background, faint hairline, radius-12, space-24
|
|
4
|
+
* padding. Dialog and Panel bind these; there is no Surface component. */
|
|
5
|
+
export const surfaceVars = {
|
|
6
|
+
bg: "var(--psi-bg-secondary)",
|
|
7
|
+
border: "var(--psi-border-faint)",
|
|
8
|
+
radius: "var(--psi-radius-12)",
|
|
9
|
+
padding: "var(--psi-space-24)",
|
|
10
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Switch component tokens (--psi-switch-*). */
|
|
2
|
+
export const switchVars = {
|
|
3
|
+
fg: "var(--psi-fg-primary)",
|
|
4
|
+
"track-bg": "var(--psi-fill-neutral4)",
|
|
5
|
+
"track-bg-checked": "var(--psi-fill-accent)",
|
|
6
|
+
"thumb-bg": "var(--psi-fill-static-white)",
|
|
7
|
+
"focus-ring": "var(--psi-border-focus)",
|
|
8
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Table component tokens (--psi-table-*) — D62. Pure indirection, same
|
|
2
|
+
* posture as menu.ts (D53) and panel.ts: the container aliases the shared
|
|
3
|
+
* surface family, row states reuse Menu's item recipe, and per-size geometry
|
|
4
|
+
* aliases the D54/D55 control ramp so a 32px row and a 32px Button are the
|
|
5
|
+
* same 32px from one source. A brand retuning --psi-surface-* or the control
|
|
6
|
+
* ramp gets Table for free.
|
|
7
|
+
*
|
|
8
|
+
* row-bg-selected is --psi-fill-tint-accent, the same wash Button and Tag use
|
|
9
|
+
* for accent-subtle. Note --psi-fill-accent2 does NOT exist; do not write it.
|
|
10
|
+
* Geometry keys carry no bg/fg/border segment, so keyGroup() returns undefined
|
|
11
|
+
* and they stay out of scope-map.json and both D46 gates. */
|
|
12
|
+
export declare const tableVars: Record<string, string>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/** Table component tokens (--psi-table-*) — D62. Pure indirection, same
|
|
2
|
+
* posture as menu.ts (D53) and panel.ts: the container aliases the shared
|
|
3
|
+
* surface family, row states reuse Menu's item recipe, and per-size geometry
|
|
4
|
+
* aliases the D54/D55 control ramp so a 32px row and a 32px Button are the
|
|
5
|
+
* same 32px from one source. A brand retuning --psi-surface-* or the control
|
|
6
|
+
* ramp gets Table for free.
|
|
7
|
+
*
|
|
8
|
+
* row-bg-selected is --psi-fill-tint-accent, the same wash Button and Tag use
|
|
9
|
+
* for accent-subtle. Note --psi-fill-accent2 does NOT exist; do not write it.
|
|
10
|
+
* Geometry keys carry no bg/fg/border segment, so keyGroup() returns undefined
|
|
11
|
+
* and they stay out of scope-map.json and both D46 gates. */
|
|
12
|
+
export const tableVars = {
|
|
13
|
+
bg: "var(--psi-surface-bg)",
|
|
14
|
+
border: "var(--psi-surface-border)",
|
|
15
|
+
radius: "var(--psi-surface-radius)",
|
|
16
|
+
fg: "var(--psi-fg-primary)",
|
|
17
|
+
"header-fg": "var(--psi-fg-secondary)",
|
|
18
|
+
"cell-border": "var(--psi-border-faint)",
|
|
19
|
+
"row-bg": "transparent",
|
|
20
|
+
"row-bg-hover": "var(--psi-fill-neutral3)",
|
|
21
|
+
"row-bg-selected": "var(--psi-fill-tint-accent)",
|
|
22
|
+
"sort-indicator-fg": "var(--psi-fg-accent)",
|
|
23
|
+
"focus-ring": "var(--psi-border-focus)",
|
|
24
|
+
"32-row-height": "var(--psi-control-32-height)",
|
|
25
|
+
"40-row-height": "var(--psi-control-40-height)",
|
|
26
|
+
"48-row-height": "var(--psi-control-48-height)",
|
|
27
|
+
"32-cell-padding-x": "var(--psi-control-32-padding-inline)",
|
|
28
|
+
"40-cell-padding-x": "var(--psi-control-40-padding-inline)",
|
|
29
|
+
"48-cell-padding-x": "var(--psi-control-48-padding-inline)",
|
|
30
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Tabs component tokens (--psi-tabs-*) — D67. Pure indirection, same posture
|
|
2
|
+
* as menu.ts (D53), table.ts (D62) and toast.ts (D64): colour aliases the
|
|
3
|
+
* semantic layer, geometry aliases the D54/D55 control ramp so a 32px tab and
|
|
4
|
+
* a 32px Button are the same 32px from one source.
|
|
5
|
+
*
|
|
6
|
+
* No new contrast pairs: fgAccent and fgSecondary on bgPrimary are already in
|
|
7
|
+
* wcagAAPairs, and the geometry keys carry no bg/fg/border segment so
|
|
8
|
+
* keyGroup() returns undefined and they stay out of both D46 gates.
|
|
9
|
+
*
|
|
10
|
+
* fg-disabled is deliberately NOT contrast-gated. Disabled text is exempt from
|
|
11
|
+
* WCAG 1.4.3, and gating it would force a contrast that defeats the
|
|
12
|
+
* affordance — the same reasoning behind Menu's item-fg-disabled, which binds
|
|
13
|
+
* the same token. */
|
|
14
|
+
export declare const tabsVars: Record<string, string>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** Tabs component tokens (--psi-tabs-*) — D67. Pure indirection, same posture
|
|
2
|
+
* as menu.ts (D53), table.ts (D62) and toast.ts (D64): colour aliases the
|
|
3
|
+
* semantic layer, geometry aliases the D54/D55 control ramp so a 32px tab and
|
|
4
|
+
* a 32px Button are the same 32px from one source.
|
|
5
|
+
*
|
|
6
|
+
* No new contrast pairs: fgAccent and fgSecondary on bgPrimary are already in
|
|
7
|
+
* wcagAAPairs, and the geometry keys carry no bg/fg/border segment so
|
|
8
|
+
* keyGroup() returns undefined and they stay out of both D46 gates.
|
|
9
|
+
*
|
|
10
|
+
* fg-disabled is deliberately NOT contrast-gated. Disabled text is exempt from
|
|
11
|
+
* WCAG 1.4.3, and gating it would force a contrast that defeats the
|
|
12
|
+
* affordance — the same reasoning behind Menu's item-fg-disabled, which binds
|
|
13
|
+
* the same token. */
|
|
14
|
+
export const tabsVars = {
|
|
15
|
+
fg: "var(--psi-fg-secondary)",
|
|
16
|
+
"fg-selected": "var(--psi-fg-accent)",
|
|
17
|
+
"fg-disabled": "var(--psi-fg-quaternary)",
|
|
18
|
+
"bg-hover": "var(--psi-fill-neutral3)",
|
|
19
|
+
indicator: "var(--psi-fill-accent)",
|
|
20
|
+
"list-border": "var(--psi-border-faint)",
|
|
21
|
+
"focus-ring": "var(--psi-border-focus)",
|
|
22
|
+
"32-height": "var(--psi-control-32-height)",
|
|
23
|
+
"40-height": "var(--psi-control-40-height)",
|
|
24
|
+
"32-padding-x": "var(--psi-control-32-padding-inline)",
|
|
25
|
+
"40-padding-x": "var(--psi-control-40-padding-inline)",
|
|
26
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** Tag component tokens (--psi-tag-*). Solid variants map to fill + foreground
|
|
2
|
+
* pairs; subtle variants add tint fills. Warning label uses fg-static-black
|
|
3
|
+
* (D22) instead of fg-primary for contrast and visual emphasis. */
|
|
4
|
+
export declare const tagVars: Record<string, string>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** Tag component tokens (--psi-tag-*). Solid variants map to fill + foreground
|
|
2
|
+
* pairs; subtle variants add tint fills. Warning label uses fg-static-black
|
|
3
|
+
* (D22) instead of fg-primary for contrast and visual emphasis. */
|
|
4
|
+
export const tagVars = {
|
|
5
|
+
"neutral-bg": "var(--psi-fill-neutral3)",
|
|
6
|
+
"neutral-fg": "var(--psi-fg-primary)",
|
|
7
|
+
"accent-bg": "var(--psi-fill-accent)",
|
|
8
|
+
"accent-fg": "var(--psi-fg-on-accent)",
|
|
9
|
+
"success-bg": "var(--psi-fill-success)",
|
|
10
|
+
"success-fg": "var(--psi-fg-static-white)",
|
|
11
|
+
"warning-bg": "var(--psi-fill-warning)",
|
|
12
|
+
"warning-fg": "var(--psi-fg-static-black)",
|
|
13
|
+
"danger-bg": "var(--psi-fill-danger)",
|
|
14
|
+
"danger-fg": "var(--psi-fg-static-white)",
|
|
15
|
+
"neutral-subtle-bg": "var(--psi-fill-neutral2)",
|
|
16
|
+
"neutral-subtle-fg": "var(--psi-fg-secondary)",
|
|
17
|
+
"accent-subtle-bg": "var(--psi-fill-tint-accent)",
|
|
18
|
+
"accent-subtle-fg": "var(--psi-fg-accent)",
|
|
19
|
+
"success-subtle-bg": "var(--psi-fill-tint-success)",
|
|
20
|
+
"success-subtle-fg": "var(--psi-fg-success)",
|
|
21
|
+
"warning-subtle-bg": "var(--psi-fill-tint-warning)",
|
|
22
|
+
"warning-subtle-fg": "var(--psi-fg-warning)",
|
|
23
|
+
"danger-subtle-bg": "var(--psi-fill-tint-danger)",
|
|
24
|
+
"danger-subtle-fg": "var(--psi-fg-danger)",
|
|
25
|
+
"focus-ring": "var(--psi-border-focus)",
|
|
26
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/** Toast component tokens (--psi-toast-*) — D64/D65. Pure indirection, same
|
|
2
|
+
* posture as menu.ts (D53) and table.ts (D62): the card aliases the shared
|
|
3
|
+
* surface family, so a brand retuning --psi-surface-* gets Toast for free.
|
|
4
|
+
*
|
|
5
|
+
* The variant lives in the status icon's colour only — Toast is an elevated
|
|
6
|
+
* surface card, not a tinted one (a stack of three saturated cards is the
|
|
7
|
+
* loudest thing on the screen, and a tint fights the elevated-surface language
|
|
8
|
+
* every other overlay speaks). The tinted alternative was measured and also
|
|
9
|
+
* passes contrast; it is rejected on design grounds, not on the gate.
|
|
10
|
+
*
|
|
11
|
+
* Note there is NO shadow key: --psi-shadow-* does not exist in any form, and
|
|
12
|
+
* neither Menu nor Dialog declares a box-shadow. Psi's elevated surfaces are
|
|
13
|
+
* border + background. Do not write --psi-shadow-overlay.
|
|
14
|
+
*
|
|
15
|
+
* The three semantic icon foregrounds sit on bgSecondary (what --psi-surface-bg
|
|
16
|
+
* resolves to), so contrast-matrix.ts gates fgSuccess/fgWarning/fgDanger there
|
|
17
|
+
* as well as on bgPrimary. Tightest measured margin is 5.87 (light) against a
|
|
18
|
+
* 4.5 floor. */
|
|
19
|
+
export declare const toastVars: Record<string, string>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** Toast component tokens (--psi-toast-*) — D64/D65. Pure indirection, same
|
|
2
|
+
* posture as menu.ts (D53) and table.ts (D62): the card aliases the shared
|
|
3
|
+
* surface family, so a brand retuning --psi-surface-* gets Toast for free.
|
|
4
|
+
*
|
|
5
|
+
* The variant lives in the status icon's colour only — Toast is an elevated
|
|
6
|
+
* surface card, not a tinted one (a stack of three saturated cards is the
|
|
7
|
+
* loudest thing on the screen, and a tint fights the elevated-surface language
|
|
8
|
+
* every other overlay speaks). The tinted alternative was measured and also
|
|
9
|
+
* passes contrast; it is rejected on design grounds, not on the gate.
|
|
10
|
+
*
|
|
11
|
+
* Note there is NO shadow key: --psi-shadow-* does not exist in any form, and
|
|
12
|
+
* neither Menu nor Dialog declares a box-shadow. Psi's elevated surfaces are
|
|
13
|
+
* border + background. Do not write --psi-shadow-overlay.
|
|
14
|
+
*
|
|
15
|
+
* The three semantic icon foregrounds sit on bgSecondary (what --psi-surface-bg
|
|
16
|
+
* resolves to), so contrast-matrix.ts gates fgSuccess/fgWarning/fgDanger there
|
|
17
|
+
* as well as on bgPrimary. Tightest measured margin is 5.87 (light) against a
|
|
18
|
+
* 4.5 floor. */
|
|
19
|
+
export const toastVars = {
|
|
20
|
+
bg: "var(--psi-surface-bg)",
|
|
21
|
+
border: "var(--psi-surface-border)",
|
|
22
|
+
radius: "var(--psi-surface-radius)",
|
|
23
|
+
fg: "var(--psi-fg-primary)",
|
|
24
|
+
"icon-fg-neutral": "var(--psi-fg-secondary)",
|
|
25
|
+
"icon-fg-success": "var(--psi-fg-success)",
|
|
26
|
+
"icon-fg-warning": "var(--psi-fg-warning)",
|
|
27
|
+
"icon-fg-danger": "var(--psi-fg-danger)",
|
|
28
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Toolbar component tokens (--psi-toolbar-*) — D77.
|
|
2
|
+
*
|
|
3
|
+
* A deliberate default width for Toolbar's direct, unwrapped form-control
|
|
4
|
+
* children (Input/Select used bare, as the filter-toolbar preset does) —
|
|
5
|
+
* without it, their own width:100% resolves as their flex-basis and the
|
|
6
|
+
* row stacks vertically instead of reading as a toolbar. Field-wrapped
|
|
7
|
+
* controls are unaffected: Field has no width of its own, so its flex-basis
|
|
8
|
+
* already comes from content. 200px is a standalone literal, matching
|
|
9
|
+
* Dialog's width={400|560|720} precedent — no shared scale reaches this
|
|
10
|
+
* range (sizeScale tops at 48, spacingScale at 144, both for heights/gaps
|
|
11
|
+
* not component widths).
|
|
12
|
+
*/
|
|
13
|
+
export declare const toolbarVars: Record<string, string>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Toolbar component tokens (--psi-toolbar-*) — D77.
|
|
2
|
+
*
|
|
3
|
+
* A deliberate default width for Toolbar's direct, unwrapped form-control
|
|
4
|
+
* children (Input/Select used bare, as the filter-toolbar preset does) —
|
|
5
|
+
* without it, their own width:100% resolves as their flex-basis and the
|
|
6
|
+
* row stacks vertically instead of reading as a toolbar. Field-wrapped
|
|
7
|
+
* controls are unaffected: Field has no width of its own, so its flex-basis
|
|
8
|
+
* already comes from content. 200px is a standalone literal, matching
|
|
9
|
+
* Dialog's width={400|560|720} precedent — no shared scale reaches this
|
|
10
|
+
* range (sizeScale tops at 48, spacingScale at 144, both for heights/gaps
|
|
11
|
+
* not component widths).
|
|
12
|
+
*/
|
|
13
|
+
export const toolbarVars = {
|
|
14
|
+
"control-width": "200px",
|
|
15
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Tooltip component tokens (--psi-tooltip-*). Inverted colors: dark bg, light fg. */
|
|
2
|
+
export const tooltipVars = {
|
|
3
|
+
bg: "var(--psi-bg-inverted)",
|
|
4
|
+
fg: "var(--psi-fg-on-inverted)",
|
|
5
|
+
// D56: tracks a sharper theme down, never rounder than radius-6.
|
|
6
|
+
radius: "min(var(--psi-control-radius), var(--psi-radius-6))",
|
|
7
|
+
};
|