@handamade/psi-tokens 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.
@@ -0,0 +1,129 @@
1
+ {
2
+ "variants": [
3
+ {
4
+ "variant": "accent",
5
+ "intent": "Primary action, draws attention",
6
+ "typicalUse": "Submit, CTA, main action in a group"
7
+ },
8
+ {
9
+ "variant": "accent-subtle",
10
+ "intent": "Accent tone, lower visual weight",
11
+ "typicalUse": "Selected state, active filter, soft CTA"
12
+ },
13
+ {
14
+ "variant": "neutral",
15
+ "intent": "Default, structurally present",
16
+ "typicalUse": "Secondary actions, toolbar buttons"
17
+ },
18
+ {
19
+ "variant": "neutral-subtle",
20
+ "intent": "Minimal chrome",
21
+ "typicalUse": "Inline actions, table row actions"
22
+ },
23
+ {
24
+ "variant": "ghost",
25
+ "intent": "No visible container until hover",
26
+ "typicalUse": "Icon-only triggers, compact toolbars"
27
+ },
28
+ {
29
+ "variant": "outline",
30
+ "intent": "Bordered ghost — visible structure, no fill until hover",
31
+ "typicalUse": "Marketing CTA, download button; hover fills accent"
32
+ },
33
+ {
34
+ "variant": "danger",
35
+ "intent": "Destructive action",
36
+ "typicalUse": "Delete, remove, disconnect"
37
+ },
38
+ {
39
+ "variant": "danger-subtle",
40
+ "intent": "Destructive context, low urgency",
41
+ "typicalUse": "Warning badges, soft destructive hints"
42
+ },
43
+ {
44
+ "variant": "success | warning",
45
+ "intent": "Status communication (Tag only)",
46
+ "typicalUse": "Status badges, labels"
47
+ }
48
+ ],
49
+ "rules": [
50
+ "One accent per visual group; everything else neutral or ghost.",
51
+ "danger only for actions with real consequences.",
52
+ "Sizes are px numbers (24|32|40|48), never S/M/L.",
53
+ "Typography tokens are --psi-text-{size}-{lineHeight}-{weight}.",
54
+ "Override component tokens (--psi-{component}-*), not semantic tokens, for one-off theming.",
55
+ "--psi-button-font overrides button typography across all sizes (documented D34 override; ember → mono)."
56
+ ],
57
+ "states": {
58
+ "hover": "L - 0.04",
59
+ "active": "L - 0.08",
60
+ "disabled": "element opacity 0.4 (keeps hue)",
61
+ "focus": "2px ring var(--psi-{component}-focus-ring)"
62
+ },
63
+ "typographyDefaults": {
64
+ "body": "16-24-regular",
65
+ "compactUI": "14-20-regular",
66
+ "heading": "24-32-medium",
67
+ "caption": "12-16-regular"
68
+ },
69
+ "fonts": {
70
+ "roles": [
71
+ "sans",
72
+ "serif",
73
+ "mono",
74
+ "display"
75
+ ],
76
+ "note": "Font roles are brand-level (D29). The DS ships no font files: consumers load each brand's webfonts themselves.",
77
+ "brands": {
78
+ "ember": {
79
+ "archivo": "800,900 (display/sans)",
80
+ "ibmPlexSerif": "400 (serif)",
81
+ "ibmPlexMono": "400,500 (mono)"
82
+ }
83
+ },
84
+ "scope": "Brand font stacks fully apply when data-psi-theme is on the root <html> element (the standard consumer setup). In nested subtree theming, --psi-text-*/--psi-display-* combos keep the default stacks: custom properties substitute at :root."
85
+ },
86
+ "motion": {
87
+ "durations": [
88
+ 150,
89
+ 200,
90
+ 350,
91
+ 450,
92
+ 600
93
+ ],
94
+ "easings": {
95
+ "standard": "ease",
96
+ "in-out": "ease-in-out",
97
+ "soft": "cubic-bezier(0.2, 0.6, 0.2, 1)"
98
+ },
99
+ "reducedMotion": "All --psi-duration-* zero under prefers-reduced-motion (D30). Always drive transitions/animations with duration tokens; never hardcode times.",
100
+ "recipes": {
101
+ "pulseDown": "App-level keyframe (the DS ships none): @keyframes pulse-down { 0%,100% { transform: translateY(0); opacity: .5; } 50% { transform: translateY(6px); opacity: 1; } } — drive with var(--psi-ease-in-out)."
102
+ }
103
+ },
104
+ "layout": {
105
+ "breakpoints": {
106
+ "sm": 560,
107
+ "md": 960
108
+ },
109
+ "note": "Breakpoints are build-time constants (D31): import { breakpoints } from '@handamade/psi-tokens/types'. CSS vars cannot drive @media.",
110
+ "container": "Use .psi-container — max-width 1312px, gutter 40px stepping to 24px under md.",
111
+ "zIndex": {
112
+ "nav": 100,
113
+ "overlay": 1000,
114
+ "tooltip": 1100
115
+ }
116
+ },
117
+ "recipes": {
118
+ "mediaTint": "Apply .psi-media-tint to media elements; the brand defines --psi-media-tint (D35). Hover/focus reveals true color over --psi-duration-450 --psi-ease-soft.",
119
+ "sectionHeader": "SectionHeader ships as a recipe, not a component (v1.2 non-goal): baseline-aligned flex row — mono annotation (--psi-text-mono-14-20-regular, --psi-fg-accent) + h2 (.psi-display-32-32-extrabold) + optional trailing meta, border-bottom 1px var(--psi-border-faint), padding-bottom var(--psi-space-20)."
120
+ },
121
+ "tags": {
122
+ "accentRule": "Tags are passive labels and do not count against 'one accent per visual group' — that rule governs interactive emphasis (buttons/CTAs). D40.",
123
+ "badges": {
124
+ "highlight": "accent-subtle",
125
+ "meta": "neutral-subtle",
126
+ "status": "success | warning | danger"
127
+ }
128
+ }
129
+ }
package/dist/light.css ADDED
@@ -0,0 +1,47 @@
1
+ @layer psi.theme {
2
+ :root, [data-psi-theme="light"] {
3
+ --psi-palette-obsidian: oklch(0.25 0.02 250);
4
+ --psi-palette-platinum: oklch(0.95 0.005 250);
5
+ --psi-palette-sapphire: oklch(0.55 0.21 260);
6
+ --psi-palette-ruby: oklch(0.55 0.22 25);
7
+ --psi-palette-amber: oklch(0.75 0.1582 75);
8
+ --psi-palette-emerald: oklch(0.52 0.19 155);
9
+ --psi-palette-white: oklch(1 0 0);
10
+ --psi-palette-black: oklch(0 0 0);
11
+ --psi-bg-primary: var(--psi-palette-platinum);
12
+ --psi-bg-secondary: oklch(from var(--psi-palette-platinum) calc(l + 0.03) c h);
13
+ --psi-fg-primary: oklch(from var(--psi-palette-obsidian) 0.3 0.03 h);
14
+ --psi-fg-secondary: oklch(from var(--psi-fg-primary) l c h / 0.7);
15
+ --psi-fg-tertiary: oklch(from var(--psi-fg-primary) l c h / 0.5);
16
+ --psi-fg-quaternary: oklch(from var(--psi-fg-primary) l c h / 0.3);
17
+ --psi-fg-primary-inverted: var(--psi-palette-platinum);
18
+ --psi-fg-static-white: oklch(from var(--psi-palette-platinum) 1 0 h);
19
+ --psi-fg-static-black: oklch(from var(--psi-palette-obsidian) 0.25 min(c, 0.03) h);
20
+ --psi-fg-on-accent: var(--psi-fg-static-white);
21
+ --psi-fg-accent: oklch(from var(--psi-palette-sapphire) 0.48 min(c, 0.23) h);
22
+ --psi-fg-success: oklch(from var(--psi-palette-emerald) 0.48 min(c, 0.1187) h);
23
+ --psi-fg-warning: oklch(from var(--psi-palette-amber) 0.48 min(c, 0.1013) h);
24
+ --psi-fg-danger: oklch(from var(--psi-palette-ruby) 0.48 min(c, 0.1946) h);
25
+ --psi-fill-neutral1: oklch(from var(--psi-palette-platinum) calc(l + 0.016) calc(c - 0.001) h);
26
+ --psi-fill-neutral2: var(--psi-palette-platinum);
27
+ --psi-fill-neutral3: oklch(from var(--psi-palette-platinum) calc(l - 0.017) calc(c + 0.001) h);
28
+ --psi-fill-neutral4: oklch(from var(--psi-palette-platinum) calc(l - 0.034) calc(c + 0.002) h);
29
+ --psi-fill-neutral5: oklch(from var(--psi-palette-platinum) calc(l - 0.032) calc(c + 0.003) h);
30
+ --psi-fill-neutral6: oklch(from var(--psi-palette-platinum) calc(l - 0.048) calc(c + 0.004) h);
31
+ --psi-fill-accent: var(--psi-palette-sapphire);
32
+ --psi-fill-success: oklch(from var(--psi-palette-emerald) l min(c, 0.1285) h);
33
+ --psi-fill-warning: var(--psi-palette-amber);
34
+ --psi-fill-danger: var(--psi-palette-ruby);
35
+ --psi-fill-tint-accent: oklch(from var(--psi-fg-accent) l c h / 0.12);
36
+ --psi-fill-tint-success: oklch(from var(--psi-fg-success) l c h / 0.12);
37
+ --psi-fill-tint-warning: oklch(from var(--psi-fg-warning) l c h / 0.12);
38
+ --psi-fill-tint-danger: oklch(from var(--psi-fg-danger) l c h / 0.12);
39
+ --psi-border-faint: oklch(from var(--psi-fg-primary) l c h / 0.08);
40
+ --psi-border-neutral: oklch(from var(--psi-fg-primary) l c h / 0.15);
41
+ --psi-border-strong: oklch(from var(--psi-fg-primary) l c h / 0.3);
42
+ --psi-border-focus: var(--psi-fg-accent);
43
+ --psi-scrim-soft: oklch(from var(--psi-bg-primary) l c h / 0.25);
44
+ --psi-scrim-medium: oklch(from var(--psi-bg-primary) l c h / 0.35);
45
+ --psi-scrim-heavy: oklch(from var(--psi-bg-primary) l c h / 0.82);
46
+ }
47
+ }