haus-tokens 0.1.2 → 0.2.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 hipuku
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # haus-tokens
2
2
 
3
- The haus design tokens OKLCH colour, type, spacing, radius, shadow, motion
3
+ The haus design tokens: OKLCH colour, type, spacing, radius, shadow and motion,
4
4
  in three forms, from one source of truth.
5
5
 
6
6
  | Form | Import | For |
@@ -30,14 +30,25 @@ them meaning, `motion` adds duration and easing. All three are wrapped in
30
30
  ```
31
31
  primitives.css --aronia-500: oklch(52% 0.138 300)
32
32
 
33
- semantics.css --primary-default: var(--aronia-500)
33
+ semantics.css --color-primary-default: var(--aronia-500)
34
34
 
35
- your component background: var(--primary-default)
35
+ your component background: var(--color-primary-default)
36
36
  ```
37
37
 
38
- **Components must never reference a primitive directly.** A primitive is a raw
39
- value with no opinion; a semantic token carries the decision. Reaching past the
40
- semantic layer is what makes a theme swap impossible later.
38
+ A primitive is a raw value with no opinion; a semantic token carries the
39
+ decision. Components read the semantic layer for colour, type, spacing, radius,
40
+ elevation and motion, and reaching past it is what makes a theme swap
41
+ impossible later.
42
+
43
+ Two kinds of primitive read are documented rather than hidden. Sizes: 31
44
+ declarations across the haus components take a size off the space ladder, on
45
+ `height`, `width`, `min-*`/`max-*` and `transform` offsets, because a size is a
46
+ value rather than a role. They are the avatar sizes, the checkbox and radio
47
+ boxes, the toggle track and thumb, and a few min/max bounds. And 56 read a primitive that has no semantic alias
48
+ because the primitive's own name already is the role: `--font-sans`,
49
+ `--weight-*`, `--border-width-*`, `--opacity-disabled`, `--icon-sm`,
50
+ `--z-modal`. No component reads a colour, radius, shadow or motion primitive,
51
+ and a test in `haus-components` holds that line.
41
52
 
42
53
  ## Typed constants
43
54
 
@@ -48,19 +59,19 @@ can't read CSS. The JS export covers that:
48
59
  import { tokens } from 'haus-tokens'
49
60
 
50
61
  tokens.color.aronia[500] // 'oklch(52% 0.138 300)'
51
- tokens.breakpoint.lg // '1024px' breakpoints are JS-only, by necessity
62
+ tokens.breakpoint.lg // '1024px', breakpoints are JS-only by necessity
52
63
  tokens.motion['fade-in'] // '200ms cubic-bezier(0.00, 0.00, 0.20, 1.00)'
53
64
  ```
54
65
 
55
66
  This is the **primitive** layer only. Semantic tokens live in `semantics.css`
56
- and in `tokens.json`, because their whole job is to be swappable at runtime
57
- freezing them into a JS constant would defeat the point.
67
+ and in `tokens.json`, because their whole job is to be swappable at runtime.
68
+ Freezing them into a JS constant would defeat the point.
58
69
 
59
70
  ## The DTCG JSON
60
71
 
61
72
  `tokens.json` conforms to the [W3C Design Tokens](https://tr.designtokens.org/format/)
62
73
  format, so it round-trips through design tooling. It stores *typed* values
63
- rather than CSS strings a font family is an array, a cubic-bezier is four
74
+ rather than CSS strings: a font family is an array, a cubic-bezier is four
64
75
  numbers, a composite is an alias:
65
76
 
66
77
  ```jsonc
@@ -72,13 +83,20 @@ numbers, a composite is an alias:
72
83
  ## Three copies, one truth
73
84
 
74
85
  Stating the same tokens three times invites exactly the drift this design
75
- system exists to prevent so `tokens.test.ts` checks it mechanically on every
76
- run. It compares all three forms *after* resolving DTCG's typed values and
77
- aliases, so a real value change fails the build while a formatting difference
78
- does not, and it fails if any form declares a token the others don't.
79
-
80
- That covers 133 tokens against the JSON and 112 against the CSS. Change a value
81
- in one place and the suite tells you about the other two.
86
+ system exists to prevent. So two of the three are not stated at all:
87
+ `tokens.json` is the source, and `primitives.css` and `index.ts` are generated
88
+ from it by `scripts/build-tokens.ts`. `pnpm run tokens:check` regenerates them
89
+ in memory and fails if what is committed differs, which is the first step CI
90
+ runs. Change a value in `tokens.json` and `pnpm run tokens` writes the other
91
+ two; change one of the other two by hand and CI says so.
92
+
93
+ `semantics.css` is the one token file still written by hand, because a role is a
94
+ decision rather than a derivation. `semantics.test.ts` holds it to the rules
95
+ this package states: every token it reads is declared in the layers below, no
96
+ declaration carries a raw value, every subtle and default surface has its
97
+ paired `on-*` text token, every interactive scale has a disabled state, no
98
+ colour role names a palette, and a spacing step is the same size whichever of
99
+ the three roles reads it.
82
100
 
83
101
  ## Licence
84
102
 
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/* ─── haus / tokens ──────────────────────────────────────────────────────────\n Typed constants for the primitive layer.\n\n The CSS custom properties are the runtime form; this exists for the places\n they cannot reach @media conditions, build config, style-in-JS. Semantic\n tokens are deliberately absent: their whole job is to be swappable at\n runtime, which freezing them into a constant would defeat.\n\n GENERATED FROM src/tokens.json do not edit.\n Regenerate with `npm run tokens`; `npm run tokens:check` fails CI if stale.\n ─────────────────────────────────────────────────────────────────────────── */\n\nexport const tokens = {\n color: {\n aronia: {\n \"100\": \"oklch(97% 0.012 300)\",\n \"200\": \"oklch(92% 0.028 300)\",\n \"300\": \"oklch(84% 0.058 300)\",\n \"400\": \"oklch(72% 0.100 300)\",\n \"500\": \"oklch(52% 0.138 300)\",\n \"600\": \"oklch(43% 0.125 300)\",\n \"700\": \"oklch(35% 0.105 300)\",\n \"800\": \"oklch(26% 0.080 300)\",\n \"900\": \"oklch(18% 0.052 300)\",\n \"950\": \"oklch(12% 0.032 300)\",\n },\n damson: {\n \"0\": \"oklch(100% 0 0)\",\n \"50\": \"oklch(99% 0.003 290)\",\n \"100\": \"oklch(97% 0.006 290)\",\n \"200\": \"oklch(93% 0.008 290)\",\n \"300\": \"oklch(86% 0.010 290)\",\n \"400\": \"oklch(74% 0.010 290)\",\n \"500\": \"oklch(60% 0.008 290)\",\n \"600\": \"oklch(48% 0.007 290)\",\n \"700\": \"oklch(37% 0.006 290)\",\n \"800\": \"oklch(27% 0.005 290)\",\n \"900\": \"oklch(18% 0.003 290)\",\n \"950\": \"oklch(11% 0.002 290)\",\n },\n elderberry: {\n \"100\": \"oklch(97% 0.020 265)\",\n \"200\": \"oklch(93% 0.040 265)\",\n \"400\": \"oklch(74% 0.160 265)\",\n \"500\": \"oklch(55% 0.200 265)\",\n \"700\": \"oklch(42% 0.160 265)\",\n \"900\": \"oklch(30% 0.120 265)\",\n },\n greengage: {\n \"100\": \"oklch(97% 0.030 148)\",\n \"200\": \"oklch(93% 0.055 148)\",\n \"400\": \"oklch(75% 0.150 148)\",\n \"500\": \"oklch(58% 0.185 148)\",\n \"700\": \"oklch(45% 0.150 148)\",\n \"900\": \"oklch(33% 0.110 148)\",\n },\n mango: {\n \"100\": \"oklch(97% 0.025 65)\",\n \"200\": \"oklch(93% 0.045 65)\",\n \"400\": \"oklch(76% 0.145 65)\",\n \"500\": \"oklch(60% 0.175 65)\",\n \"700\": \"oklch(47% 0.142 65)\",\n \"900\": \"oklch(38% 0.110 65)\",\n },\n cherry: {\n \"100\": \"oklch(97% 0.030 27)\",\n \"200\": \"oklch(93% 0.055 27)\",\n \"400\": \"oklch(74% 0.160 27)\",\n \"500\": \"oklch(58% 0.200 27)\",\n \"700\": \"oklch(44% 0.168 27)\",\n \"900\": \"oklch(33% 0.110 27)\",\n },\n },\n font: {\n family: {\n sans: \"'Manrope', system-ui, sans-serif\",\n mono: \"'Fira Code', ui-monospace, monospace\",\n },\n size: {\n \"11\": \"0.6875rem\",\n \"12\": \"0.75rem\",\n \"13\": \"0.8125rem\",\n \"14\": \"0.875rem\",\n \"16\": \"1rem\",\n \"20\": \"1.25rem\",\n \"24\": \"1.5rem\",\n \"30\": \"1.875rem\",\n },\n weight: {\n regular: 400,\n medium: 500,\n semibold: 600,\n bold: 700,\n },\n lineHeight: {\n tight: 1.15,\n tighter: 1.2,\n snug: 1.25,\n compact: 1.3,\n normal: 1.4,\n relaxed: 1.5,\n loose: 1.6,\n },\n tracking: {\n tight: \"-0.01em\",\n normal: \"0em\",\n wide: \"0.02em\",\n widest: \"0.08em\",\n },\n },\n spacing: {\n \"1\": \"0.25rem\",\n \"2\": \"0.5rem\",\n \"3\": \"0.75rem\",\n \"4\": \"1rem\",\n \"5\": \"1.25rem\",\n \"6\": \"1.5rem\",\n \"7\": \"1.75rem\",\n \"8\": \"2rem\",\n \"10\": \"2.5rem\",\n \"12\": \"3rem\",\n \"16\": \"4rem\",\n \"20\": \"5rem\",\n },\n radius: {\n none: \"0\",\n sm: \"0.25rem\",\n md: \"0.5rem\",\n lg: \"0.75rem\",\n xl: \"1rem\",\n \"2xl\": \"1.5rem\",\n full: \"9999px\",\n },\n duration: {\n instant: \"50ms\",\n fast: \"100ms\",\n normal: \"200ms\",\n moderate: \"300ms\",\n slow: \"500ms\",\n },\n easing: {\n enter: \"cubic-bezier(0.00, 0.00, 0.20, 1.00)\",\n exit: \"cubic-bezier(0.40, 0.00, 1.00, 1.00)\",\n move: \"cubic-bezier(0.40, 0.00, 0.20, 1.00)\",\n spring: \"cubic-bezier(0.34, 1.56, 0.64, 1.00)\",\n linear: \"linear\",\n },\n motion: {\n \"fade-in\": \"200ms cubic-bezier(0.00, 0.00, 0.20, 1.00)\",\n \"fade-out\": \"100ms cubic-bezier(0.40, 0.00, 1.00, 1.00)\",\n \"slide-in\": \"300ms cubic-bezier(0.00, 0.00, 0.20, 1.00)\",\n \"slide-out\": \"100ms cubic-bezier(0.40, 0.00, 1.00, 1.00)\",\n micro: \"100ms cubic-bezier(0.40, 0.00, 0.20, 1.00)\",\n interactive: \"200ms cubic-bezier(0.40, 0.00, 0.20, 1.00)\",\n },\n shadow: {\n none: \"none\",\n sm: \"0 1px 2px oklch(18% 0.003 290 / 0.06)\",\n md: \"0 4px 6px -1px oklch(18% 0.003 290 / 0.10), 0 2px 4px -2px oklch(18% 0.003 290 / 0.10)\",\n lg: \"0 10px 15px -3px oklch(18% 0.003 290 / 0.10), 0 4px 6px -4px oklch(18% 0.003 290 / 0.07)\",\n xl: \"0 20px 25px -5px oklch(18% 0.003 290 / 0.10), 0 8px 10px -6px oklch(18% 0.003 290 / 0.10)\",\n },\n zIndex: {\n base: 0,\n raised: 10,\n dropdown: 100,\n sticky: 200,\n overlay: 300,\n modal: 400,\n toast: 500,\n tooltip: 600,\n },\n borderWidth: {\n default: \"1px\",\n thick: \"2px\",\n },\n opacity: {\n disabled: 0.4,\n overlay: 0.6,\n },\n iconSize: {\n xs: \"0.75rem\",\n sm: \"1rem\",\n md: \"1.25rem\",\n lg: \"1.5rem\",\n xl: \"2rem\",\n },\n breakpoint: {\n sm: \"640px\",\n md: \"768px\",\n lg: \"1024px\",\n xl: \"1280px\",\n \"2xl\": \"1536px\",\n },\n} as const\n\nexport type Tokens = typeof tokens\n"]}
1
+ {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";AAYO,IAAM,MAAA,GAAS;AAAA,EACpB,KAAA,EAAO;AAAA,IACL,MAAA,EAAQ;AAAA,MACN,KAAA,EAAO,sBAAA;AAAA,MACP,KAAA,EAAO,sBAAA;AAAA,MACP,KAAA,EAAO,sBAAA;AAAA,MACP,KAAA,EAAO,sBAAA;AAAA,MACP,KAAA,EAAO,sBAAA;AAAA,MACP,KAAA,EAAO,sBAAA;AAAA,MACP,KAAA,EAAO,sBAAA;AAAA,MACP,KAAA,EAAO,sBAAA;AAAA,MACP,KAAA,EAAO,sBAAA;AAAA,MACP,KAAA,EAAO;AAAA,KACT;AAAA,IACA,MAAA,EAAQ;AAAA,MACN,GAAA,EAAK,iBAAA;AAAA,MACL,IAAA,EAAM,sBAAA;AAAA,MACN,KAAA,EAAO,sBAAA;AAAA,MACP,KAAA,EAAO,sBAAA;AAAA,MACP,KAAA,EAAO,sBAAA;AAAA,MACP,KAAA,EAAO,sBAAA;AAAA,MACP,KAAA,EAAO,sBAAA;AAAA,MACP,KAAA,EAAO,sBAAA;AAAA,MACP,KAAA,EAAO,sBAAA;AAAA,MACP,KAAA,EAAO,sBAAA;AAAA,MACP,KAAA,EAAO,sBAAA;AAAA,MACP,KAAA,EAAO;AAAA,KACT;AAAA,IACA,UAAA,EAAY;AAAA,MACV,KAAA,EAAO,sBAAA;AAAA,MACP,KAAA,EAAO,sBAAA;AAAA,MACP,KAAA,EAAO,sBAAA;AAAA,MACP,KAAA,EAAO,sBAAA;AAAA,MACP,KAAA,EAAO,sBAAA;AAAA,MACP,KAAA,EAAO;AAAA,KACT;AAAA,IACA,SAAA,EAAW;AAAA,MACT,KAAA,EAAO,sBAAA;AAAA,MACP,KAAA,EAAO,sBAAA;AAAA,MACP,KAAA,EAAO,sBAAA;AAAA,MACP,KAAA,EAAO,sBAAA;AAAA,MACP,KAAA,EAAO,sBAAA;AAAA,MACP,KAAA,EAAO;AAAA,KACT;AAAA,IACA,KAAA,EAAO;AAAA,MACL,KAAA,EAAO,qBAAA;AAAA,MACP,KAAA,EAAO,qBAAA;AAAA,MACP,KAAA,EAAO,qBAAA;AAAA,MACP,KAAA,EAAO,qBAAA;AAAA,MACP,KAAA,EAAO,qBAAA;AAAA,MACP,KAAA,EAAO;AAAA,KACT;AAAA,IACA,MAAA,EAAQ;AAAA,MACN,KAAA,EAAO,qBAAA;AAAA,MACP,KAAA,EAAO,qBAAA;AAAA,MACP,KAAA,EAAO,qBAAA;AAAA,MACP,KAAA,EAAO,qBAAA;AAAA,MACP,KAAA,EAAO,qBAAA;AAAA,MACP,KAAA,EAAO;AAAA;AACT,GACF;AAAA,EACA,IAAA,EAAM;AAAA,IACJ,MAAA,EAAQ;AAAA,MACN,IAAA,EAAM,kCAAA;AAAA,MACN,IAAA,EAAM;AAAA,KACR;AAAA,IACA,IAAA,EAAM;AAAA,MACJ,IAAA,EAAM,WAAA;AAAA,MACN,IAAA,EAAM,SAAA;AAAA,MACN,IAAA,EAAM,WAAA;AAAA,MACN,IAAA,EAAM,UAAA;AAAA,MACN,IAAA,EAAM,MAAA;AAAA,MACN,IAAA,EAAM,SAAA;AAAA,MACN,IAAA,EAAM,QAAA;AAAA,MACN,IAAA,EAAM;AAAA,KACR;AAAA,IACA,MAAA,EAAQ;AAAA,MACN,OAAA,EAAS,GAAA;AAAA,MACT,MAAA,EAAQ,GAAA;AAAA,MACR,QAAA,EAAU,GAAA;AAAA,MACV,IAAA,EAAM;AAAA,KACR;AAAA,IACA,UAAA,EAAY;AAAA,MACV,KAAA,EAAO,IAAA;AAAA,MACP,OAAA,EAAS,GAAA;AAAA,MACT,IAAA,EAAM,IAAA;AAAA,MACN,OAAA,EAAS,GAAA;AAAA,MACT,MAAA,EAAQ,GAAA;AAAA,MACR,OAAA,EAAS,GAAA;AAAA,MACT,KAAA,EAAO;AAAA,KACT;AAAA,IACA,QAAA,EAAU;AAAA,MACR,KAAA,EAAO,SAAA;AAAA,MACP,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,QAAA;AAAA,MACN,MAAA,EAAQ;AAAA;AACV,GACF;AAAA,EACA,OAAA,EAAS;AAAA,IACP,GAAA,EAAK,SAAA;AAAA,IACL,GAAA,EAAK,QAAA;AAAA,IACL,GAAA,EAAK,SAAA;AAAA,IACL,GAAA,EAAK,MAAA;AAAA,IACL,GAAA,EAAK,SAAA;AAAA,IACL,GAAA,EAAK,QAAA;AAAA,IACL,GAAA,EAAK,SAAA;AAAA,IACL,GAAA,EAAK,MAAA;AAAA,IACL,IAAA,EAAM,QAAA;AAAA,IACN,IAAA,EAAM,MAAA;AAAA,IACN,IAAA,EAAM,MAAA;AAAA,IACN,IAAA,EAAM;AAAA,GACR;AAAA,EACA,MAAA,EAAQ;AAAA,IACN,IAAA,EAAM,GAAA;AAAA,IACN,EAAA,EAAI,SAAA;AAAA,IACJ,EAAA,EAAI,QAAA;AAAA,IACJ,EAAA,EAAI,SAAA;AAAA,IACJ,EAAA,EAAI,MAAA;AAAA,IACJ,KAAA,EAAO,QAAA;AAAA,IACP,IAAA,EAAM;AAAA,GACR;AAAA,EACA,QAAA,EAAU;AAAA,IACR,OAAA,EAAS,MAAA;AAAA,IACT,IAAA,EAAM,OAAA;AAAA,IACN,MAAA,EAAQ,OAAA;AAAA,IACR,QAAA,EAAU,OAAA;AAAA,IACV,IAAA,EAAM;AAAA,GACR;AAAA,EACA,MAAA,EAAQ;AAAA,IACN,KAAA,EAAO,sCAAA;AAAA,IACP,IAAA,EAAM,sCAAA;AAAA,IACN,IAAA,EAAM,sCAAA;AAAA,IACN,MAAA,EAAQ,sCAAA;AAAA,IACR,MAAA,EAAQ;AAAA,GACV;AAAA,EACA,MAAA,EAAQ;AAAA,IACN,SAAA,EAAW,4CAAA;AAAA,IACX,UAAA,EAAY,4CAAA;AAAA,IACZ,UAAA,EAAY,4CAAA;AAAA,IACZ,WAAA,EAAa,4CAAA;AAAA,IACb,KAAA,EAAO,4CAAA;AAAA,IACP,WAAA,EAAa;AAAA,GACf;AAAA,EACA,MAAA,EAAQ;AAAA,IACN,IAAA,EAAM,MAAA;AAAA,IACN,EAAA,EAAI,uCAAA;AAAA,IACJ,EAAA,EAAI,wFAAA;AAAA,IACJ,EAAA,EAAI,0FAAA;AAAA,IACJ,EAAA,EAAI;AAAA,GACN;AAAA,EACA,MAAA,EAAQ;AAAA,IACN,IAAA,EAAM,CAAA;AAAA,IACN,MAAA,EAAQ,EAAA;AAAA,IACR,QAAA,EAAU,GAAA;AAAA,IACV,MAAA,EAAQ,GAAA;AAAA,IACR,OAAA,EAAS,GAAA;AAAA,IACT,KAAA,EAAO,GAAA;AAAA,IACP,KAAA,EAAO,GAAA;AAAA,IACP,OAAA,EAAS;AAAA,GACX;AAAA,EACA,WAAA,EAAa;AAAA,IACX,OAAA,EAAS,KAAA;AAAA,IACT,KAAA,EAAO;AAAA,GACT;AAAA,EACA,OAAA,EAAS;AAAA,IACP,QAAA,EAAU,GAAA;AAAA,IACV,OAAA,EAAS;AAAA,GACX;AAAA,EACA,QAAA,EAAU;AAAA,IACR,EAAA,EAAI,SAAA;AAAA,IACJ,EAAA,EAAI,MAAA;AAAA,IACJ,EAAA,EAAI,SAAA;AAAA,IACJ,EAAA,EAAI,QAAA;AAAA,IACJ,EAAA,EAAI;AAAA,GACN;AAAA,EACA,UAAA,EAAY;AAAA,IACV,EAAA,EAAI,OAAA;AAAA,IACJ,EAAA,EAAI,OAAA;AAAA,IACJ,EAAA,EAAI,QAAA;AAAA,IACJ,EAAA,EAAI,QAAA;AAAA,IACJ,KAAA,EAAO;AAAA;AAEX","file":"index.js","sourcesContent":["/* ─── haus / tokens ──────────────────────────────────────────────────────────\n Typed constants for the primitive layer.\n\n The CSS custom properties are the runtime form; this exists for the places\n they cannot reach: @media conditions, build config, style-in-JS. Semantic\n tokens are deliberately absent: their whole job is to be swappable at\n runtime, which freezing them into a constant would defeat.\n\n GENERATED FROM src/tokens.json. Do not edit.\n Regenerate with `npm run tokens`; `npm run tokens:check` fails CI if stale.\n ─────────────────────────────────────────────────────────────────────────── */\n\nexport const tokens = {\n color: {\n aronia: {\n \"100\": \"oklch(97% 0.012 300)\",\n \"200\": \"oklch(92% 0.028 300)\",\n \"300\": \"oklch(84% 0.058 300)\",\n \"400\": \"oklch(72% 0.100 300)\",\n \"500\": \"oklch(52% 0.138 300)\",\n \"600\": \"oklch(43% 0.125 300)\",\n \"700\": \"oklch(35% 0.105 300)\",\n \"800\": \"oklch(26% 0.080 300)\",\n \"900\": \"oklch(18% 0.052 300)\",\n \"950\": \"oklch(12% 0.032 300)\",\n },\n damson: {\n \"0\": \"oklch(100% 0 0)\",\n \"50\": \"oklch(99% 0.003 290)\",\n \"100\": \"oklch(97% 0.006 290)\",\n \"200\": \"oklch(93% 0.008 290)\",\n \"300\": \"oklch(86% 0.010 290)\",\n \"400\": \"oklch(74% 0.010 290)\",\n \"500\": \"oklch(60% 0.008 290)\",\n \"600\": \"oklch(48% 0.007 290)\",\n \"700\": \"oklch(37% 0.006 290)\",\n \"800\": \"oklch(27% 0.005 290)\",\n \"900\": \"oklch(18% 0.003 290)\",\n \"950\": \"oklch(11% 0.002 290)\",\n },\n elderberry: {\n \"100\": \"oklch(97% 0.020 265)\",\n \"200\": \"oklch(93% 0.040 265)\",\n \"400\": \"oklch(74% 0.160 265)\",\n \"500\": \"oklch(55% 0.200 265)\",\n \"700\": \"oklch(42% 0.160 265)\",\n \"900\": \"oklch(30% 0.120 265)\",\n },\n greengage: {\n \"100\": \"oklch(97% 0.030 148)\",\n \"200\": \"oklch(93% 0.055 148)\",\n \"400\": \"oklch(75% 0.150 148)\",\n \"500\": \"oklch(58% 0.185 148)\",\n \"700\": \"oklch(45% 0.150 148)\",\n \"900\": \"oklch(33% 0.110 148)\",\n },\n mango: {\n \"100\": \"oklch(97% 0.025 65)\",\n \"200\": \"oklch(93% 0.045 65)\",\n \"400\": \"oklch(76% 0.145 65)\",\n \"500\": \"oklch(60% 0.175 65)\",\n \"700\": \"oklch(47% 0.142 65)\",\n \"900\": \"oklch(38% 0.110 65)\",\n },\n cherry: {\n \"100\": \"oklch(97% 0.030 27)\",\n \"200\": \"oklch(93% 0.055 27)\",\n \"400\": \"oklch(74% 0.160 27)\",\n \"500\": \"oklch(58% 0.200 27)\",\n \"700\": \"oklch(44% 0.168 27)\",\n \"900\": \"oklch(33% 0.110 27)\",\n },\n },\n font: {\n family: {\n sans: \"'Manrope', system-ui, sans-serif\",\n mono: \"'Fira Code', ui-monospace, monospace\",\n },\n size: {\n \"11\": \"0.6875rem\",\n \"12\": \"0.75rem\",\n \"13\": \"0.8125rem\",\n \"14\": \"0.875rem\",\n \"16\": \"1rem\",\n \"20\": \"1.25rem\",\n \"24\": \"1.5rem\",\n \"30\": \"1.875rem\",\n },\n weight: {\n regular: 400,\n medium: 500,\n semibold: 600,\n bold: 700,\n },\n lineHeight: {\n tight: 1.15,\n tighter: 1.2,\n snug: 1.25,\n compact: 1.3,\n normal: 1.4,\n relaxed: 1.5,\n loose: 1.6,\n },\n tracking: {\n tight: \"-0.01em\",\n normal: \"0em\",\n wide: \"0.02em\",\n widest: \"0.08em\",\n },\n },\n spacing: {\n \"1\": \"0.25rem\",\n \"2\": \"0.5rem\",\n \"3\": \"0.75rem\",\n \"4\": \"1rem\",\n \"5\": \"1.25rem\",\n \"6\": \"1.5rem\",\n \"7\": \"1.75rem\",\n \"8\": \"2rem\",\n \"10\": \"2.5rem\",\n \"12\": \"3rem\",\n \"16\": \"4rem\",\n \"20\": \"5rem\",\n },\n radius: {\n none: \"0\",\n sm: \"0.25rem\",\n md: \"0.5rem\",\n lg: \"0.75rem\",\n xl: \"1rem\",\n \"2xl\": \"1.5rem\",\n full: \"9999px\",\n },\n duration: {\n instant: \"50ms\",\n fast: \"100ms\",\n normal: \"200ms\",\n moderate: \"300ms\",\n slow: \"500ms\",\n },\n easing: {\n enter: \"cubic-bezier(0.00, 0.00, 0.20, 1.00)\",\n exit: \"cubic-bezier(0.40, 0.00, 1.00, 1.00)\",\n move: \"cubic-bezier(0.40, 0.00, 0.20, 1.00)\",\n spring: \"cubic-bezier(0.34, 1.56, 0.64, 1.00)\",\n linear: \"linear\",\n },\n motion: {\n \"fade-in\": \"200ms cubic-bezier(0.00, 0.00, 0.20, 1.00)\",\n \"fade-out\": \"100ms cubic-bezier(0.40, 0.00, 1.00, 1.00)\",\n \"slide-in\": \"300ms cubic-bezier(0.00, 0.00, 0.20, 1.00)\",\n \"slide-out\": \"100ms cubic-bezier(0.40, 0.00, 1.00, 1.00)\",\n micro: \"100ms cubic-bezier(0.40, 0.00, 0.20, 1.00)\",\n interactive: \"200ms cubic-bezier(0.40, 0.00, 0.20, 1.00)\",\n },\n shadow: {\n none: \"none\",\n sm: \"0 1px 2px oklch(18% 0.003 290 / 0.06)\",\n md: \"0 4px 6px -1px oklch(18% 0.003 290 / 0.10), 0 2px 4px -2px oklch(18% 0.003 290 / 0.10)\",\n lg: \"0 10px 15px -3px oklch(18% 0.003 290 / 0.10), 0 4px 6px -4px oklch(18% 0.003 290 / 0.07)\",\n xl: \"0 20px 25px -5px oklch(18% 0.003 290 / 0.10), 0 8px 10px -6px oklch(18% 0.003 290 / 0.10)\",\n },\n zIndex: {\n base: 0,\n raised: 10,\n dropdown: 100,\n sticky: 200,\n overlay: 300,\n modal: 400,\n toast: 500,\n tooltip: 600,\n },\n borderWidth: {\n default: \"1px\",\n thick: \"2px\",\n },\n opacity: {\n disabled: 0.4,\n overlay: 0.6,\n },\n iconSize: {\n xs: \"0.75rem\",\n sm: \"1rem\",\n md: \"1.25rem\",\n lg: \"1.5rem\",\n xl: \"2rem\",\n },\n breakpoint: {\n sm: \"640px\",\n md: \"768px\",\n lg: \"1024px\",\n xl: \"1280px\",\n \"2xl\": \"1536px\",\n },\n} as const\n\nexport type Tokens = typeof tokens\n"]}
package/dist/motion.css CHANGED
@@ -1,6 +1,6 @@
1
1
  /* ─── haus / motion ──────────────────────────────────────────────────────────
2
2
  Easing curves and durations.
3
- All animation tokens live here components must not hardcode values.
3
+ All animation tokens live here. Components must not hardcode values.
4
4
  ─────────────────────────────────────────────────────────────────────────── */
5
5
 
6
6
  @layer haus.motion {
@@ -16,19 +16,19 @@
16
16
 
17
17
  /* ── Easing curves ────────────────────────────────────────────────────── */
18
18
 
19
- /* Elements appearing start slow, arrive with energy */
19
+ /* Elements appearing: start slow, arrive with energy */
20
20
  --ease-enter: cubic-bezier(0.00, 0.00, 0.20, 1.00);
21
21
 
22
- /* Elements leaving leave quickly, no lingering */
22
+ /* Elements leaving: leave quickly, no lingering */
23
23
  --ease-exit: cubic-bezier(0.40, 0.00, 1.00, 1.00);
24
24
 
25
- /* Position changes within the UI balanced, physical */
25
+ /* Position changes within the UI: balanced, physical */
26
26
  --ease-move: cubic-bezier(0.40, 0.00, 0.20, 1.00);
27
27
 
28
- /* Spring-like slight overshoot for interactive feedback */
28
+ /* Spring-like, with slight overshoot for interactive feedback */
29
29
  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1.00);
30
30
 
31
- /* Linear for opacity fades where easing adds no value */
31
+ /* Linear, for opacity fades where easing adds no value */
32
32
  --ease-linear: linear;
33
33
 
34
34
  /* ── Composite motion tokens (duration + easing pairs) ─────────────────── */
@@ -1,9 +1,9 @@
1
1
  /* ─── haus / primitives ──────────────────────────────────────────────────────
2
2
  Raw values only. No component or semantic meaning.
3
3
  Nothing outside this file should define raw values.
4
- Components must never reference these directly use semantics.css.
4
+ Components must never reference these directly. Use semantics.css.
5
5
 
6
- GENERATED FROM src/tokens.json do not edit.
6
+ GENERATED FROM src/tokens.json. Do not edit.
7
7
  Regenerate with `npm run tokens`; `npm run tokens:check` fails CI if stale.
8
8
  ─────────────────────────────────────────────────────────────────────────── */
9
9
 
@@ -16,7 +16,7 @@
16
16
  --aronia-200: oklch(92% 0.028 300);
17
17
  --aronia-300: oklch(84% 0.058 300);
18
18
  --aronia-400: oklch(72% 0.100 300);
19
- --aronia-500: oklch(52% 0.138 300); /* Default dusty plum anchor */
19
+ --aronia-500: oklch(52% 0.138 300); /* Default: dusty plum anchor */
20
20
  --aronia-600: oklch(43% 0.125 300); /* Hover */
21
21
  --aronia-700: oklch(35% 0.105 300); /* Pressed / on-subtle text */
22
22
  --aronia-800: oklch(26% 0.080 300);
@@ -24,10 +24,10 @@
24
24
  --aronia-950: oklch(12% 0.032 300);
25
25
 
26
26
  /* ── Damson (Cool Neutral) ── H=290°, very low chroma ────────────────────── */
27
- /* Same hue family as Aronia monochromatic, highly cohesive. */
27
+ /* Same hue family as Aronia, so the pairing is monochromatic and highly cohesive. */
28
28
  --damson-0: oklch(100% 0 0); /* White */
29
- --damson-50: oklch(99% 0.003 290); /* Near-white barely-lavender cool cream */
30
- --damson-100: oklch(97% 0.006 290); /* Subtle surface cool cream */
29
+ --damson-50: oklch(99% 0.003 290); /* Near-white: barely-lavender cool cream */
30
+ --damson-100: oklch(97% 0.006 290); /* Subtle surface: cool cream */
31
31
  --damson-200: oklch(93% 0.008 290); /* Sunken surface / default border */
32
32
  --damson-300: oklch(86% 0.010 290); /* Strong border */
33
33
  --damson-400: oklch(74% 0.010 290); /* Disabled / muted */
@@ -91,7 +91,7 @@
91
91
  --leading-tight: 1.15; /* Display */
92
92
  --leading-tighter: 1.2; /* heading-lg */
93
93
  --leading-snug: 1.25; /* Heading */
94
- --leading-compact: 1.3; /* Heading-sm between snug and normal */
94
+ --leading-compact: 1.3; /* Heading-sm, between snug and normal */
95
95
  --leading-normal: 1.4; /* Labels, short UI text */
96
96
  --leading-relaxed: 1.5; /* Body */
97
97
  --leading-loose: 1.6; /* Body-lg, code */
@@ -124,8 +124,8 @@
124
124
  --radius-2xl: 1.5rem; /* Panels, dialogs, sheets */
125
125
  --radius-full: 9999px;
126
126
 
127
- /* ── Shadows tinted with damson H=290° ─────────────────────────────────── */
128
- /* --shadow-focus is in semantics.css it references semantic colour tokens. */
127
+ /* ── Shadows, tinted with damson H=290° ──────────────────────────────────── */
128
+ /* --shadow-focus is in semantics.css, because it references semantic colour tokens. */
129
129
  --shadow-none: none;
130
130
  --shadow-sm: 0 1px 2px oklch(18% 0.003 290 / 0.06); /* Subtle card lift, form inputs */
131
131
  --shadow-md: 0 4px 6px -1px oklch(18% 0.003 290 / 0.10), 0 2px 4px -2px oklch(18% 0.003 290 / 0.10); /* Dropdowns, select menus */
@@ -140,7 +140,7 @@
140
140
  --z-overlay: 300; /* Sheet backgrounds, scrim */
141
141
  --z-modal: 400; /* Dialogs, modals */
142
142
  --z-toast: 500; /* Toast notifications */
143
- --z-tooltip: 600; /* Tooltips always on top */
143
+ --z-tooltip: 600; /* Tooltips, always on top */
144
144
 
145
145
  /* ── Border width ────────────────────────────────────────────────────────── */
146
146
  --border-width-default: 1px; /* Borders, dividers, inputs */
@@ -150,12 +150,12 @@
150
150
  --opacity-disabled: 0.4; /* Disabled elements */
151
151
  --opacity-overlay: 0.6; /* Scrim / backdrop */
152
152
 
153
- /* ── Icon sizes (Font Awesome pairs with type scale) ───────────────────── */
154
- --icon-xs: 0.75rem; /* 12px with label-xs */
155
- --icon-sm: 1rem; /* 16px with label, body-sm */
156
- --icon-md: 1.25rem; /* 20px with body-lg, heading-sm */
157
- --icon-lg: 1.5rem; /* 24px with heading */
158
- --icon-xl: 2rem; /* 32px standalone / decorative */
153
+ /* ── Icon sizes (Font Awesome, paired with the type scale) ───────────────── */
154
+ --icon-xs: 0.75rem; /* 12px, with label-xs */
155
+ --icon-sm: 1rem; /* 16px, with label and body-sm */
156
+ --icon-md: 1.25rem; /* 20px, with body-lg and heading-sm */
157
+ --icon-lg: 1.5rem; /* 24px, with heading */
158
+ --icon-xl: 2rem; /* 32px, standalone or decorative */
159
159
 
160
160
  }
161
161
  }
@@ -1,8 +1,24 @@
1
1
  /* ─── haus / semantics ───────────────────────────────────────────────────────
2
2
  Intent aliases. Light mode only.
3
- No component references a primitive directly.
4
3
  No raw values live in this file.
5
4
 
5
+ Components read a role from this layer for colour, padding, gap, margin,
6
+ radius, elevation and motion. Two kinds of primitive read remain in the
7
+ components, both deliberate:
8
+
9
+ · 31 declarations take a size off the space ladder, on height, width,
10
+ min/max and transform offsets: the avatar sizes and its status dot, the
11
+ checkbox and radio boxes, the toggle track and thumb and the thumb's
12
+ travel, the modal's close button and max height, the toast and modal
13
+ entry offsets, the textarea's minimum height and the select chevron's
14
+ offset. A size is a value, not a role, and calling a 16px checkbox
15
+ --space-inset-md would say something untrue.
16
+ · 56 read a primitive that has no alias here because its own name already
17
+ is the role: --font-sans, --weight-*, --border-width-*, --tracking-normal,
18
+ --opacity-disabled, --icon-sm, --z-modal.
19
+
20
+ No component reads a colour, radius, shadow or motion primitive.
21
+
6
22
  Naming rules:
7
23
  · Brand colour uses a role name at this layer: primary (aronia).
8
24
  Palette names only appear in primitives.css.
@@ -22,7 +38,7 @@
22
38
  --color-surface-default: var(--damson-0);
23
39
  --color-surface-subtle: var(--damson-100);
24
40
  --color-surface-raised: var(--damson-0); /* elevation via shadow, not colour */
25
- --color-surface-overlay: var(--damson-50); /* modal / popover barely off-white */
41
+ --color-surface-overlay: var(--damson-50); /* modal / popover, barely off-white */
26
42
  --color-surface-sunken: var(--damson-200);
27
43
  --color-surface-inverse: var(--damson-900); /* dark chip, tooltip bg in light mode */
28
44
  --color-surface-disabled: var(--damson-100);
@@ -43,7 +59,7 @@
43
59
  --color-border-focus: var(--color-primary-default);
44
60
  --color-border-disabled: var(--damson-200);
45
61
 
46
- /* ── Primary Aronia ─────────────────────────────────────────────────── */
62
+ /* ── Primary: Aronia ─────────────────────────────────────────────────── */
47
63
  --color-primary-default: var(--aronia-500);
48
64
  --color-primary-hover: var(--aronia-600);
49
65
  --color-primary-pressed: var(--aronia-700);
@@ -51,7 +67,7 @@
51
67
  --color-primary-on-subtle: var(--aronia-700);
52
68
  --color-primary-disabled: var(--damson-200);
53
69
 
54
- /* ── Feedback Info (Elderberry · Indigo) ────────────────────────────── */
70
+ /* ── Feedback: Info (Elderberry · Indigo) ────────────────────────────── */
55
71
  --color-info-subtle: var(--elderberry-100);
56
72
  --color-info-border: var(--elderberry-200);
57
73
  --color-info-default: var(--elderberry-500);
@@ -59,25 +75,25 @@
59
75
  --color-info-on-default: var(--damson-0);
60
76
  --color-info-emphasis: var(--elderberry-900);
61
77
 
62
- /* ── Feedback Success (Greengage · Green) ───────────────────────────── */
78
+ /* ── Feedback: Success (Greengage · Green) ───────────────────────────── */
63
79
  --color-success-subtle: var(--greengage-100);
64
80
  --color-success-border: var(--greengage-200);
65
81
  --color-success-default: var(--greengage-500);
66
82
  --color-success-on-subtle: var(--greengage-700);
67
- --color-success-on-default: var(--damson-900); /* dark text greengage-500 fails with white */
83
+ --color-success-on-default: var(--damson-900); /* dark text, because greengage-500 fails with white */
68
84
  --color-success-solid: var(--greengage-700); /* 700-level: white text passes at 6.82:1 */
69
85
  --color-success-emphasis: var(--greengage-900);
70
86
 
71
- /* ── Feedback Warning (Mango · Golden) ──────────────────────────────── */
87
+ /* ── Feedback: Warning (Mango · Golden) ──────────────────────────────── */
72
88
  --color-warning-subtle: var(--mango-100);
73
89
  --color-warning-border: var(--mango-200);
74
90
  --color-warning-default: var(--mango-500);
75
91
  --color-warning-on-subtle: var(--mango-700);
76
- --color-warning-on-default: var(--damson-900); /* dark text mango-500 fails with white */
92
+ --color-warning-on-default: var(--damson-900); /* dark text, because mango-500 fails with white */
77
93
  --color-warning-solid: var(--mango-700); /* 700-level: white text passes at 7.05:1 */
78
94
  --color-warning-emphasis: var(--mango-900);
79
95
 
80
- /* ── Feedback Error (Cherry · Red) ─────────────────────────────────── */
96
+ /* ── Feedback: Error (Cherry · Red) ─────────────────────────────────── */
81
97
  --color-error-subtle: var(--cherry-100);
82
98
  --color-error-border: var(--cherry-200);
83
99
  --color-error-default: var(--cherry-500);
@@ -99,7 +115,7 @@
99
115
  /* ── Focus ring ───────────────────────────────────────────────────────── */
100
116
  /* Inner ring matches surface (creates gap), outer ring is focus colour */
101
117
  --shadow-focus: 0 0 0 2px var(--color-surface-default), 0 0 0 4px var(--color-border-focus);
102
- /* Same ring in the error state the outer band carries the error colour */
118
+ /* Same ring in the error state, with the outer band carrying the error colour */
103
119
  /* so an invalid field stays legible as invalid while focused. */
104
120
  --shadow-focus-error: 0 0 0 2px var(--color-surface-default), 0 0 0 4px var(--color-error-default);
105
121
 
@@ -161,5 +177,63 @@
161
177
  --type-mono-leading: var(--leading-loose);
162
178
  --type-mono-tracking: var(--tracking-normal);
163
179
 
180
+
181
+ /* ── Spacing ─────────────────────────────────────────────────────────────
182
+ Three roles over one ladder: inset is padding, gap is space between
183
+ siblings, stack is margin. A step is the same size whichever role reads
184
+ it, so the roles stay comparable. Splitting them is what lets padding be
185
+ retuned later without moving page rhythm, and without first working out
186
+ which --space-3 meant which.
187
+
188
+ Only the steps components use are named. Add one when a component needs
189
+ it, rather than reaching past this layer. */
190
+
191
+ /* Padding: space inside a component, between its edge and its content. */
192
+ --space-inset-2xs: var(--space-1); /* 4px */
193
+ --space-inset-xs: var(--space-2); /* 8px */
194
+ --space-inset-sm: var(--space-3); /* 12px */
195
+ --space-inset-md: var(--space-4); /* 16px */
196
+ --space-inset-lg: var(--space-5); /* 20px */
197
+ --space-inset-xl: var(--space-6); /* 24px */
198
+ --space-inset-2xl: var(--space-8); /* 32px */
199
+
200
+ /* Gap: space between siblings, set by the parent. */
201
+ --space-gap-2xs: var(--space-1); /* 4px */
202
+ --space-gap-xs: var(--space-2); /* 8px */
203
+ --space-gap-sm: var(--space-3); /* 12px */
204
+ --space-gap-md: var(--space-4); /* 16px */
205
+
206
+ /* Stack: margin, space a component asks for around itself. */
207
+ --space-stack-2xs: var(--space-1); /* 4px */
208
+ --space-stack-xs: var(--space-2); /* 8px */
209
+
210
+ /* ── Radius ──────────────────────────────────────────────────────────────
211
+ Named for what is rounded, so a component asks for the shape of the
212
+ thing rather than a size off the ramp. */
213
+ --radius-control: var(--radius-md); /* Button, Input, Select, Textarea */
214
+ --radius-surface: var(--radius-lg); /* Card, Toast */
215
+ --radius-overlay: var(--radius-xl); /* Modal */
216
+ --radius-marker: var(--radius-sm); /* Checkbox, Modal/Toast icons */
217
+ --radius-pill: var(--radius-full); /* Badge, Toggle track */
218
+
219
+ /* ── Elevation ───────────────────────────────────────────────────────────
220
+ Named for how high the thing sits, rather than how large its shadow is. */
221
+ --elevation-raised: var(--shadow-sm); /* Toggle knob */
222
+ --elevation-floating: var(--shadow-lg); /* Card, Toast */
223
+ --elevation-overlay: var(--shadow-xl); /* Modal */
224
+
225
+ /* ── Motion ──────────────────────────────────────────────────────────────
226
+ Named for what moves. The curves and the reduced-motion duration are
227
+ already roles in motion.css and are read from there. */
228
+ --motion-duration-emphasis: var(--duration-slow); /* Button's loading sweep */
229
+
230
+ /* Sizes are not spacing. Marker boxes, avatar sizes, the toggle's travel
231
+ and a few min/max bounds read the primitive ladder directly: they are
232
+ values, and naming them as inset or gap would say something untrue about
233
+ what they are. Thirty-one declarations do this deliberately.
234
+ Button, Input and Select set min-height in raw pixels instead, which is
235
+ neither, and is issue territory rather than a decision recorded here. */
236
+
237
+
164
238
  }
165
239
  }
package/dist/tokens.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "200": { "$value": "oklch(92% 0.028 300)" },
8
8
  "300": { "$value": "oklch(84% 0.058 300)" },
9
9
  "400": { "$value": "oklch(72% 0.100 300)" },
10
- "500": { "$value": "oklch(52% 0.138 300)", "$description": "Default dusty plum anchor" },
10
+ "500": { "$value": "oklch(52% 0.138 300)", "$description": "Default: dusty plum anchor" },
11
11
  "600": { "$value": "oklch(43% 0.125 300)", "$description": "Hover" },
12
12
  "700": { "$value": "oklch(35% 0.105 300)", "$description": "Pressed / on-subtle text" },
13
13
  "800": { "$value": "oklch(26% 0.080 300)" },
@@ -16,8 +16,8 @@
16
16
  },
17
17
  "damson": {
18
18
  "0": { "$value": "oklch(100% 0 0)", "$description": "White" },
19
- "50": { "$value": "oklch(99% 0.003 290)", "$description": "Near-white barely-lavender cool cream" },
20
- "100": { "$value": "oklch(97% 0.006 290)", "$description": "Subtle surface cool cream" },
19
+ "50": { "$value": "oklch(99% 0.003 290)", "$description": "Near-white: barely-lavender cool cream" },
20
+ "100": { "$value": "oklch(97% 0.006 290)", "$description": "Subtle surface: cool cream" },
21
21
  "200": { "$value": "oklch(93% 0.008 290)", "$description": "Sunken surface / default border" },
22
22
  "300": { "$value": "oklch(86% 0.010 290)", "$description": "Strong border" },
23
23
  "400": { "$value": "oklch(74% 0.010 290)", "$description": "Disabled / muted" },
@@ -29,7 +29,7 @@
29
29
  "950": { "$value": "oklch(11% 0.002 290)", "$description": "Near-black" }
30
30
  },
31
31
  "elderberry": {
32
- "$description": "Indigo H=265°, distinct from aronia H=300°",
32
+ "$description": "Indigo at H=265°, distinct from aronia H=300°",
33
33
  "100": { "$value": "oklch(97% 0.020 265)", "$description": "Subtle background" },
34
34
  "200": { "$value": "oklch(93% 0.040 265)", "$description": "Subtle border" },
35
35
  "400": { "$value": "oklch(74% 0.160 265)", "$description": "Icon on subtle background" },
@@ -38,7 +38,7 @@
38
38
  "900": { "$value": "oklch(30% 0.120 265)", "$description": "Emphasis / high-contrast text" }
39
39
  },
40
40
  "greengage": {
41
- "$description": "Green H=148°",
41
+ "$description": "Green at H=148°",
42
42
  "100": { "$value": "oklch(97% 0.030 148)", "$description": "Subtle background" },
43
43
  "200": { "$value": "oklch(93% 0.055 148)", "$description": "Subtle border" },
44
44
  "400": { "$value": "oklch(75% 0.150 148)", "$description": "Icon on subtle background" },
@@ -47,7 +47,7 @@
47
47
  "900": { "$value": "oklch(33% 0.110 148)", "$description": "Emphasis / high-contrast text" }
48
48
  },
49
49
  "mango": {
50
- "$description": "Golden H=65°",
50
+ "$description": "Golden at H=65°",
51
51
  "100": { "$value": "oklch(97% 0.025 65)", "$description": "Subtle background" },
52
52
  "200": { "$value": "oklch(93% 0.045 65)", "$description": "Subtle border" },
53
53
  "400": { "$value": "oklch(76% 0.145 65)", "$description": "Icon on subtle background" },
@@ -56,7 +56,7 @@
56
56
  "900": { "$value": "oklch(38% 0.110 65)", "$description": "Emphasis / high-contrast text" }
57
57
  },
58
58
  "cherry": {
59
- "$description": "Red H=27°",
59
+ "$description": "Red at H=27°",
60
60
  "100": { "$value": "oklch(97% 0.030 27)", "$description": "Subtle background" },
61
61
  "200": { "$value": "oklch(93% 0.055 27)", "$description": "Subtle border" },
62
62
  "400": { "$value": "oklch(74% 0.160 27)", "$description": "Icon on subtle background" },
@@ -90,7 +90,7 @@
90
90
  "tight": { "$type": "number", "$value": 1.15, "$description": "Display" },
91
91
  "tighter": { "$type": "number", "$value": 1.2, "$description": "heading-lg" },
92
92
  "snug": { "$type": "number", "$value": 1.25, "$description": "Heading" },
93
- "compact": { "$type": "number", "$value": 1.30, "$description": "Heading-sm between snug and normal" },
93
+ "compact": { "$type": "number", "$value": 1.30, "$description": "Heading-sm, between snug and normal" },
94
94
  "normal": { "$type": "number", "$value": 1.40, "$description": "Labels, short UI text" },
95
95
  "relaxed": { "$type": "number", "$value": 1.50, "$description": "Body" },
96
96
  "loose": { "$type": "number", "$value": 1.60, "$description": "Body-lg, code" }
@@ -118,12 +118,12 @@
118
118
  "20": { "$value": "5rem", "$description": "80px" }
119
119
  },
120
120
  "semantic": {
121
- "$description": "Intent aliases over primitives. Components reference these only never primitives directly.",
121
+ "$description": "Intent aliases over primitives. Components reference these only, and never primitives directly.",
122
122
  "color": {
123
123
  "$type": "color",
124
124
  "surface-default": { "$value": "{color.damson.0}", "$description": "Page / default surface" },
125
125
  "surface-subtle": { "$value": "{color.damson.100}", "$description": "Subtle container, hover bg" },
126
- "surface-raised": { "$value": "{color.damson.0}", "$description": "Card surface elevation via shadow" },
126
+ "surface-raised": { "$value": "{color.damson.0}", "$description": "Card surface, with elevation via shadow" },
127
127
  "surface-overlay": { "$value": "{color.damson.50}", "$description": "Modal / popover background" },
128
128
  "surface-sunken": { "$value": "{color.damson.200}", "$description": "Inset / well surface" },
129
129
  "surface-inverse": { "$value": "{color.damson.900}", "$description": "Dark chip, inverse surface" },
@@ -137,7 +137,7 @@
137
137
  "ink-link": { "$value": "{color.aronia.500}", "$description": "Anchor link colour" },
138
138
  "ink-on-aronia": { "$value": "{color.damson.0}", "$description": "Text on primary-filled surfaces" },
139
139
 
140
- "border-subtle": { "$value": "{color.damson.100}", "$description": "Faintest border section dividers" },
140
+ "border-subtle": { "$value": "{color.damson.100}", "$description": "Faintest border, for section dividers" },
141
141
  "border-default": { "$value": "{color.damson.200}", "$description": "Standard border" },
142
142
  "border-strong": { "$value": "{color.damson.300}", "$description": "Emphasis border" },
143
143
  "border-focus": { "$value": "{color.aronia.500}", "$description": "Keyboard focus ring colour" },
@@ -161,16 +161,16 @@
161
161
  "success-border": { "$value": "{color.greengage.200}" },
162
162
  "success-default": { "$value": "{color.greengage.500}" },
163
163
  "success-on-subtle": { "$value": "{color.greengage.700}" },
164
- "success-on-default": { "$value": "{color.damson.900}", "$description": "Dark text greengage-500 fails with white" },
165
- "success-solid": { "$value": "{color.greengage.700}", "$description": "Solid badge bg white text passes at 6.82:1" },
164
+ "success-on-default": { "$value": "{color.damson.900}", "$description": "Dark text, because greengage-500 fails with white" },
165
+ "success-solid": { "$value": "{color.greengage.700}", "$description": "Solid badge bg, white text passes at 6.82:1" },
166
166
  "success-emphasis": { "$value": "{color.greengage.900}" },
167
167
 
168
168
  "warning-subtle": { "$value": "{color.mango.100}" },
169
169
  "warning-border": { "$value": "{color.mango.200}" },
170
170
  "warning-default": { "$value": "{color.mango.500}" },
171
171
  "warning-on-subtle": { "$value": "{color.mango.700}" },
172
- "warning-on-default": { "$value": "{color.damson.900}", "$description": "Dark text mango-500 fails with white" },
173
- "warning-solid": { "$value": "{color.mango.700}", "$description": "Solid badge bg white text passes at 7.05:1" },
172
+ "warning-on-default": { "$value": "{color.damson.900}", "$description": "Dark text, because mango-500 fails with white" },
173
+ "warning-solid": { "$value": "{color.mango.700}", "$description": "Solid badge bg, white text passes at 7.05:1" },
174
174
  "warning-emphasis": { "$value": "{color.mango.900}" },
175
175
 
176
176
  "error-subtle": { "$value": "{color.cherry.100}" },
@@ -180,10 +180,10 @@
180
180
  "error-on-default": { "$value": "{color.damson.0}" },
181
181
  "error-emphasis": { "$value": "{color.cherry.900}" },
182
182
 
183
- "backdrop": { "$value": "{color.damson.950}", "$description": "Modal scrim applied at --opacity-overlay (0.6) in CSS" },
184
- "border-inverse": { "$value": "{color.damson.0}", "$description": "Button border on dark surface 30% alpha applied in CSS" },
185
- "border-inverse-hover": { "$value": "{color.damson.0}", "$description": "Hover border on dark surface 50% alpha applied in CSS" },
186
- "surface-inverse-hover": { "$value": "{color.damson.0}", "$description": "Hover bg on dark surface 10% alpha applied in CSS" }
183
+ "backdrop": { "$value": "{color.damson.950}", "$description": "Modal scrim, applied at --opacity-overlay (0.6) in CSS" },
184
+ "border-inverse": { "$value": "{color.damson.0}", "$description": "Button border on dark surface, 30% alpha applied in CSS" },
185
+ "border-inverse-hover": { "$value": "{color.damson.0}", "$description": "Hover border on dark surface, 50% alpha applied in CSS" },
186
+ "surface-inverse-hover": { "$value": "{color.damson.0}", "$description": "Hover bg on dark surface, 10% alpha applied in CSS" }
187
187
  }
188
188
  },
189
189
  "radius": {
@@ -205,9 +205,9 @@
205
205
  "slow": { "$value": "500ms" }
206
206
  },
207
207
  "easing": {
208
- "enter": { "$type": "cubicBezier", "$value": [0.00, 0.00, 0.20, 1.00], "$description": "Elements appearing start slow, arrive with energy" },
209
- "exit": { "$type": "cubicBezier", "$value": [0.40, 0.00, 1.00, 1.00], "$description": "Elements leaving leave quickly, no lingering" },
210
- "move": { "$type": "cubicBezier", "$value": [0.40, 0.00, 0.20, 1.00], "$description": "Position changes balanced, physical" },
208
+ "enter": { "$type": "cubicBezier", "$value": [0.00, 0.00, 0.20, 1.00], "$description": "Elements appearing: start slow, arrive with energy" },
209
+ "exit": { "$type": "cubicBezier", "$value": [0.40, 0.00, 1.00, 1.00], "$description": "Elements leaving: leave quickly, no lingering" },
210
+ "move": { "$type": "cubicBezier", "$value": [0.40, 0.00, 0.20, 1.00], "$description": "Position changes: balanced, physical" },
211
211
  "spring": { "$type": "cubicBezier", "$value": [0.34, 1.56, 0.64, 1.00], "$description": "Slight overshoot for interactive feedback" },
212
212
  "linear": { "$type": "string", "$value": "linear", "$description": "For opacity fades where easing adds no value" }
213
213
  },
@@ -226,7 +226,7 @@
226
226
  "md": { "$type": "string", "$value": "0 4px 6px -1px oklch(18% 0.003 290 / 0.10), 0 2px 4px -2px oklch(18% 0.003 290 / 0.10)", "$description": "Dropdowns, select menus" },
227
227
  "lg": { "$type": "string", "$value": "0 10px 15px -3px oklch(18% 0.003 290 / 0.10), 0 4px 6px -4px oklch(18% 0.003 290 / 0.07)", "$description": "Modals, dialogs" },
228
228
  "xl": { "$type": "string", "$value": "0 20px 25px -5px oklch(18% 0.003 290 / 0.10), 0 8px 10px -6px oklch(18% 0.003 290 / 0.10)", "$description": "Full-page overlays" },
229
- "focus": { "$type": "string", "$value": "0 0 0 2px {color.surface-default}, 0 0 0 4px {color.primary-default}", "$description": "Keyboard focus ring defined in semantics layer" }
229
+ "focus": { "$type": "string", "$value": "0 0 0 2px {color.surface-default}, 0 0 0 4px {color.primary-default}", "$description": "Keyboard focus ring, defined in the semantics layer" }
230
230
  },
231
231
  "zIndex": {
232
232
  "$type": "number",
@@ -237,7 +237,7 @@
237
237
  "overlay": { "$value": 300, "$description": "Sheet backgrounds, scrim" },
238
238
  "modal": { "$value": 400, "$description": "Dialogs, modals" },
239
239
  "toast": { "$value": 500, "$description": "Toast notifications" },
240
- "tooltip": { "$value": 600, "$description": "Tooltips always on top" }
240
+ "tooltip": { "$value": 600, "$description": "Tooltips, always on top" }
241
241
  },
242
242
  "borderWidth": {
243
243
  "$type": "dimension",
@@ -252,11 +252,11 @@
252
252
  "iconSize": {
253
253
  "$type": "dimension",
254
254
  "$description": "Font Awesome. Sizes pair with the type scale.",
255
- "xs": { "$value": "0.75rem", "$description": "12px with label-xs" },
256
- "sm": { "$value": "1rem", "$description": "16px with label, body-sm" },
257
- "md": { "$value": "1.25rem", "$description": "20px with body-lg, heading-sm" },
258
- "lg": { "$value": "1.5rem", "$description": "24px with heading" },
259
- "xl": { "$value": "2rem", "$description": "32px standalone / decorative" }
255
+ "xs": { "$value": "0.75rem", "$description": "12px, with label-xs" },
256
+ "sm": { "$value": "1rem", "$description": "16px, with label and body-sm" },
257
+ "md": { "$value": "1.25rem", "$description": "20px, with body-lg and heading-sm" },
258
+ "lg": { "$value": "1.5rem", "$description": "24px, with heading" },
259
+ "xl": { "$value": "2rem", "$description": "32px, standalone or decorative" }
260
260
  },
261
261
  "breakpoint": {
262
262
  "$description": "CSS custom properties cannot be used in @media queries. Consume from index.ts in JS/TS and Tailwind config instead.",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "haus-tokens",
3
- "version": "0.1.2",
4
- "description": "haus design tokens OKLCH colour, type, spacing, radius, shadow and motion, as W3C-DTCG JSON, CSS custom properties, and typed JS constants.",
3
+ "version": "0.2.0",
4
+ "description": "haus design tokens: OKLCH colour, type, spacing, radius, shadow and motion, as W3C-DTCG JSON, CSS custom properties, and typed JS constants.",
5
5
  "license": "MIT",
6
6
  "author": "hipuku",
7
7
  "homepage": "https://github.com/hipuku/haus/tree/main/packages/tokens#readme",
@@ -39,16 +39,19 @@
39
39
  "files": [
40
40
  "dist"
41
41
  ],
42
+ "devDependencies": {
43
+ "@types/node": "^22.0.0",
44
+ "tsup": "^8.5.1",
45
+ "tsx": "^4.23.12",
46
+ "typescript": "^5.4.5",
47
+ "vitest": "^4.1.11"
48
+ },
42
49
  "scripts": {
43
50
  "build": "tsup",
44
51
  "typecheck": "tsc --noEmit",
45
- "prepublishOnly": "npm run tokens:check && npm run build",
46
52
  "tokens": "tsx scripts/build-tokens.ts",
47
- "tokens:check": "tsx scripts/build-tokens.ts --check"
48
- },
49
- "devDependencies": {
50
- "tsup": "^8.5.1",
51
- "tsx": "^4.23.12",
52
- "typescript": "^5.4.5"
53
+ "tokens:check": "tsx scripts/build-tokens.ts --check",
54
+ "test": "vitest run",
55
+ "test:watch": "vitest"
53
56
  }
54
- }
57
+ }