@uncinq/design-tokens 1.7.3 → 1.8.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 CHANGED
@@ -4,488 +4,99 @@
4
4
 
5
5
  <img width="1280" height="640" alt="share-design-tokens" src="https://github.com/user-attachments/assets/66b8ce73-b07d-4cd0-bcb7-f8e0f7a5bb98" />
6
6
 
7
- ## What are design tokens?
7
+ Primitive and semantic design tokens, authored in [DTCG](https://tr.designtokens.org/format/) JSON and compiled to CSS custom properties by [Style Dictionary](https://styledictionary.com/).
8
8
 
9
- Design tokens are the atomic decisions of a design system: colors, spacing, typography, motion. Instead of hardcoding `#ae003f` or `1rem` throughout your codebase, you name the decision — `--color-brand`, `--spacing-md` — and reference that name everywhere.
10
-
11
- ## Token architecture
12
-
13
- This package follows the [DTCG](docs/DTCG.md) three-layer model — primitive → semantic → component:
14
-
15
- ```
16
- primitive → semantic → component
17
- (raw values) (purpose) (component-scoped, not in this package)
18
- ```
19
-
20
- ### Layer 1 — Primitive
21
-
22
- Raw, context-free values. No opinions about where they're used.
23
-
24
- ```css
25
- --color-indigo-600: #4338ca;
26
- --size-16: 1rem;
27
- --font-weight-bold: 700;
28
- ```
29
-
30
- A primitive token answers: **"what is the value?"**
31
-
32
- ### Layer 2 — Semantic
33
-
34
- Named by purpose, not by appearance. References primitives via CSS `var()`.
35
-
36
- ```css
37
- --color-brand: var(--color-indigo-600);
38
- --spacing-md: var(--size-30);
39
- --font-weight-heading: var(--font-weight-bold);
40
- ```
41
-
42
- A semantic token answers: **"what is this value for?"**
43
-
44
- This is the layer that gives portability: all projects consuming `@uncinq/design-tokens` share the same semantic API. When the brand color changes, you update one primitive — all semantic tokens that reference it update automatically.
45
-
46
- ### Layer 3 — Component
47
-
48
- Scoped to a specific component. Generic component tokens are provided by [@uncinq/component-tokens](https://github.com/uncinq/component-tokens); project-specific ones live in each project's own design system.
49
-
50
- ```css
51
- --alert-border-radius: var(--radius-none);
52
- --btn-padding-inline: var(--spacing-control);
53
- --btn-padding-block: var(--spacing-control);
54
- ```
55
-
56
- ---
57
-
58
- ## Naming convention
59
-
60
- ### Semantic tokens
61
-
62
- Global semantic tokens follow: `--{category}-{subcategory?}-{variant}-{state?}`
63
-
64
- ```
65
- --{category} --color
66
- -{subcategory} --color-text
67
- -{variant} --color-text-muted
68
- -{state} --color-text-disabled
69
- ```
70
-
71
- ### Component tokens
72
-
73
- Component tokens follow: `--{component}-{property}-{sub-property?}-{state?}`
74
-
75
- The property mirrors the CSS property name, so the token reads the same way as the CSS declaration it controls — colors excepted, where `color` leads and the role follows (see the rules below).
9
+ ## Installation
76
10
 
11
+ ```bash
12
+ npm install @uncinq/design-tokens
77
13
  ```
78
- --{component} --btn
79
- -{property} --btn-padding-inline
80
- -{sub-property} --btn-color-text-decoration (color + text-decoration)
81
- -{state} --btn-color-background-hover
82
- ```
83
-
84
- ### Rules
85
-
86
- - **Lowercase kebab-case** — always
87
- - **No component names** in primitive or semantic tokens (`--button-*` belongs in component tokens, not here)
88
- - **Semantic tokens are named by intent** — they may reference a primitive via `var()` or carry a raw value when the value itself has design intent (e.g. `--z-index-modal: 400`, `--radius-pill: 9999px`)
89
- - **`color-[role]` for all color tokens** — `color` is the category prefix, the UI role follows: `color-background`, `color-border`, `color-text`, `color-accent`, `color-placeholder`. This groups all color tokens alphabetically under `color-*` and mirrors the structure of global semantic tokens (`--color-background` → `--btn-color-background`). `background` is never abbreviated: `color-background` not `color-bg`.
90
- - **States at the end** — `-hover`, `-focus`, `-active`, `-disabled`, `-checked`
91
- - **Alphabetical order** — tokens within a file are sorted alphabetically within each group; group related tokens with a comment when the file has many entries:
92
-
93
- | Token | Role | CSS property |
94
- | --- | --- | --- |
95
- | `--btn-color-background` | background | `background-color` |
96
- | `--btn-color-border` | border | `border-color` |
97
- | `--btn-color-text` | text | `color` |
98
- | `--btn-color-text-decoration` | text-decoration | `text-decoration-color` |
99
- | `--form-color-accent` | accent | `color` |
100
- | `--input-color-placeholder` | placeholder | `color` |
101
14
 
102
15
  ```css
103
- /* Brand */
104
- --color-brand: var(--color-indigo-600);
105
- --color-brand-hover: var(--color-indigo-700);
106
-
107
- /* Text */
108
- --color-text: var(--color-gray-900);
109
- --color-text-muted: var(--color-gray-500);
110
- ```
111
-
112
- ### Scales
113
-
114
- | Use case | Scale | Example |
115
- | --- | --- | --- |
116
- | Color palettes | Numeric `100–900` | `--color-gray-500` |
117
- | Heading levels | Zero-padded `01–06` | `--font-size-heading-01` |
118
- | Layout / spacing | T-shirt `2xs xs sm md lg xl 2xl` | `--spacing-md` |
119
- | Radius, shadow, size | T-shirt `2xs xs sm md lg xl 2xl` | `--radius-sm` |
120
- | Purposeful aliases | Named | `--radius-control`, `--radius-pill` |
121
-
122
- ### Category reference
123
-
124
- | Category | Covers | Example tokens |
125
- | --- | --- | --- |
126
- | `color` | All color values | `--color-brand`, `--color-background-muted`, `--color-text-on-dark` |
127
- | `font-family` | Typefaces | `--font-family-sans`, `--font-family-heading` |
128
- | `font-size` | Text sizes | `--font-size-sm`, `--font-size-heading-01` |
129
- | `font-weight` | Weight values | `--font-weight-bold`, `--font-weight-heading` |
130
- | `line-height` | Line heights | `--line-height-tight`, `--line-height-heading` |
131
- | `letter-spacing` | Tracking | `--letter-spacing-none`, `--letter-spacing-md` |
132
- | `text-decoration` | Decoration props | `--text-decoration-offset` |
133
- | `spacing` | Margin / padding | `--spacing-md`, `--spacing-section` |
134
- | `size` | Width / height | `--size-16`, `--size-tablet` |
135
- | `radius` | Border radius | `--radius-md`, `--radius-pill` |
136
- | `border` | Border style/width | `--border-width-sm`, `--border-style-normal` |
137
- | `shadow` | Box shadows | `--shadow-md`, `--shadow-center-sm` |
138
- | `gradient` | Overlay gradients | `--gradient-darken-color-from`, `--gradient-darken-stop` |
139
- | `duration` | Animation timing | `--duration-fast` |
140
- | `easing` | Timing functions | `--easing-bounce` |
141
- | `transition` | Shorthand transitions | `--transition-normal`, `--transition-color` |
142
- | `ratio` | Aspect ratios | `--ratio-video` |
143
- | `font-size-fluid` | Responsive fluid type scale (Utopia) | `--font-size-fluid-sm`, `--font-size-fluid-xl` |
144
- | `spacing-fluid` | Responsive fluid spacing scale (Utopia) | `--spacing-fluid-sm`, `--spacing-fluid-lg` |
145
- | `focus` | Focus ring tokens | `--focus-color`, `--focus-outline-width` |
146
- | `opacity` | Opacity values | `--opacity-disabled`, `--opacity-overlay` |
147
- | `span` | Grid column spans | `--span-full`, `--span-half` |
148
- | `z-index` | Stacking order | `--z-index-modal`, `--z-index-dropdown` |
149
- | `max-width` | Readability caps | `--max-width-paragraph` |
150
-
151
- ---
152
-
153
- ## Colors
154
-
155
- ### Color space — OKLCH
156
-
157
- All primitive color values are defined in **OKLCH** (`oklch(L C H)`):
158
-
159
- | Channel | Range | Meaning |
160
- |---------|-------|---------|
161
- | `L` | `0 → 1` | Perceptual lightness (0 = black, 1 = white) |
162
- | `C` | `0 → ~0.4` | Chroma / colorfulness (0 = gray) |
163
- | `H` | `0° → 360°` | Hue angle |
164
-
165
- **Why OKLCH over hex/HSL?**
166
-
167
- - **Perceptually uniform** — equal steps in L produce equal perceived brightness differences, regardless of hue. HSL does not guarantee this (`hsl(60, 100%, 50%)` yellow looks far brighter than `hsl(240, 100%, 50%)` blue at the same L).
168
- - **Predictable contrast** — you can reason about WCAG contrast by comparing L values without converting to relative luminance.
169
- - **Better interpolation** — gradients and animations between two OKLCH colors don't pass through muddy grays.
170
- - **Future-proof** — native in all modern browsers, the color space used by Tailwind v4, Radix, and the W3C Design Tokens spec.
171
-
172
- > Browser support: Chrome 111+, Firefox 113+, Safari 15.4+. No sRGB fallback is generated — every value ships as `oklch()`, so anything older needs a fallback of its own.
173
-
174
- ### Primitive palette
175
-
176
- The primitive palette provides **11 steps per hue** (50 → 950), named numerically. These are raw values with no opinion about usage.
177
-
178
- | Hue | H angle | Character |
179
- |-----|---------|-----------|
180
- | `amber` | ≈ 70° | Golden yellow-orange |
181
- | `blue` | ≈ 260° | Classic blue |
182
- | `cyan` | ≈ 215° | Bright cyan |
183
- | `gray` | neutral | Cool neutral |
184
- | `green` | ≈ 150° | Lush green |
185
- | `indigo` | ≈ 277° | Blue-violet |
186
- | `lime` | ≈ 131° | Electric yellow-green |
187
- | `orange` | ≈ 48° | Vivid orange |
188
- | `pink` | ≈ 354° | Bright pink |
189
- | `purple` | ≈ 304° | Rich purple |
190
- | `red` | ≈ 25° | Classic red |
191
- | `rose` | ≈ 16° | Pink-red |
192
- | `sienna` | ≈ 23° | Brick-red (crimson × terracotta) |
193
- | `sky` | ≈ 237° | Soft sky blue |
194
- | `teal` | ≈ 183° | Blue-green |
195
- | `violet` | ≈ 293° | Modern violet |
196
- | `yellow` | ≈ 86° | Pure yellow |
197
-
198
- Plus `--color-black` and `--color-white`.
199
-
200
- **Step guide:**
201
-
202
- | Step | L (avg) | L amber/yellow/lime | Typical use |
203
- |------|---------|---------------------|-------------|
204
- | 50 | ≈ 0.97 | ≈ 0.98 | Page tinted backgrounds, hover states on white |
205
- | 100 | ≈ 0.94 | ≈ 0.96 | Muted backgrounds, badges, tags |
206
- | 200 | ≈ 0.90 | ≈ 0.93 | Borders, dividers |
207
- | 300 | ≈ 0.83 | ≈ 0.88 | Disabled elements, placeholder text |
208
- | 400 | ≈ 0.72 | ≈ 0.83 | Secondary icons, decorative |
209
- | 500 | ≈ 0.63 | ≈ 0.77 | Mid-tone — use with dark text for UI |
210
- | 600 | ≈ 0.53 | ≈ 0.67 | **Default brand/status bg** — white text passes WCAG AA (UI) |
211
- | 700 | ≈ 0.46 | ≈ 0.55 | Hover state, colored text on white background |
212
- | 800 | ≈ 0.39 | ≈ 0.47 | Deep accents, high-contrast text |
213
- | 900 | ≈ 0.33 | ≈ 0.41 | Near-dark, very high contrast |
214
- | 950 | ≈ 0.22 | ≈ 0.28 | Darkest tint, almost black |
215
-
216
- > **Note on OKLCH** — L is perceptually uniform, but intrinsically bright hues (amber, yellow, lime) have naturally higher L values at steps 400–700. This is expected behavior, not a calibration error. Gray goes the other way (chroma ≈ 0, no brightness boost, L slightly lower). The "L avg" column is representative of cool chromatic hues (blue, red, green, violet…).
217
-
218
- ### Semantic color tokens
219
-
220
- Semantic tokens are named by **purpose**, not by value. They reference primitives via `var()`.
221
-
222
- #### Brand & accent
16
+ /* everything: primitive + semantic + dark theme */
17
+ @import '@uncinq/design-tokens';
223
18
 
224
- ```css
225
- --color-brand: /* primary brand color (button bg, active states…) */
226
- --color-brand-muted: /* tinted background for brand areas */
227
- --color-brand-hover: /* hover state of brand */
228
- --color-brand-strong: /* darkest brand shade */
19
+ /* or by layer */
20
+ @import '@uncinq/design-tokens/css/primitive.css';
21
+ @import '@uncinq/design-tokens/css/semantic.css';
229
22
 
230
- --color-accent: /* = brand by default; override independently if needed */
23
+ /* or file by file */
24
+ @import '@uncinq/design-tokens/css/semantic/color.css';
231
25
  ```
232
26
 
233
- The default brand is **sienna** — a warm brick-red. Override it in your project:
27
+ Without a build step:
234
28
 
235
- ```css
236
- @layer tokens {
237
- :root {
238
- --color-brand: var(--color-violet-600);
239
- --color-brand-muted: var(--color-violet-100);
240
- --color-brand-hover: var(--color-violet-700);
241
- --color-brand-strong: var(--color-violet-900);
242
- }
243
- }
29
+ ```html
30
+ <link rel="stylesheet" href="https://unpkg.com/@uncinq/design-tokens">
244
31
  ```
245
32
 
246
- #### Backgrounds
247
-
248
- | Token | Default | Usage |
249
- |-------|---------|-------|
250
- | `--color-background` | white | Page background |
251
- | `--color-background-muted` | gray-100 | Subtle section backgrounds |
252
- | `--color-background-surface` | = `--color-background` | Card / panel backgrounds |
253
- | `--color-background-media` | gray-200 | Image placeholders, skeleton loaders |
254
- | `--color-background-accent` | = `--color-accent` | Highlighted sections |
255
-
256
- #### Text
257
-
258
- | Token | Default | Usage |
259
- |-------|---------|-------|
260
- | `--color-text` | gray-900 | Body text |
261
- | `--color-text-muted` | gray-500 | Secondary, captions |
262
- | `--color-text-disabled` | gray-300 | Disabled UI |
263
- | `--color-heading` | black | Headings |
264
- | `--color-link` | = `--color-text` | Default link color |
265
- | `--color-link-hover` | = `--color-accent` | Link hover |
266
- | `--color-active` | = `--color-accent` | Active nav item |
267
- | `--color-credit` | = `--color-text-muted` | Bylines, captions |
268
-
269
- #### Text on colored backgrounds
33
+ Every generated file declares `@layer tokens` itself. Declaring the full layer order is the consuming project's job, and it must happen before any import.
270
34
 
271
- Used to ensure contrast when a color is the background:
35
+ ## Token architecture
272
36
 
273
- ```css
274
- --color-text-on-brand /* white */
275
- --color-text-on-accent /* white */
276
- --color-text-on-dark /* white */
277
- --color-text-on-light /* gray-900 */
278
- --color-text-on-surface /* = --color-text */
279
- --color-text-on-danger /* white */
280
- --color-text-on-info /* white */
281
- --color-text-on-success /* white */
282
- --color-text-on-warning /* gray-900 — amber is bright, dark text required */
283
37
  ```
284
-
285
- #### Status / semantic variants
286
-
287
- | Token | Primitive | Notes |
288
- |-------|-----------|-------|
289
- | `--color-danger` | red-600 | Errors, destructive actions |
290
- | `--color-success` | green-600 | Confirmations |
291
- | `--color-warning` | amber-500 | Warnings — use with `--color-text-on-warning` |
292
- | `--color-info` | blue-600 | Informational |
293
- | `--color-dark` | gray-900 | Dark surfaces |
294
- | `--color-light` | gray-200 | Light surfaces |
295
-
296
- Each variant has `-muted` (tinted bg) and `-strong` (hover / emphasis) companions:
297
-
298
- ```css
299
- --color-danger-muted: var(--color-red-100);
300
- --color-danger-strong: var(--color-red-800); /* used for hover */
38
+ primitive → semantic → component
39
+ (raw values) (purpose) (@uncinq/component-tokens)
301
40
  ```
302
41
 
303
- ### Accessibility (WCAG)
304
-
305
- | Ratio | Requirement |
306
- |-------|-------------|
307
- | **4.5 : 1** | Normal text (< 18px / non-bold < 14px) — WCAG AA |
308
- | **3 : 1** | Large text, UI components (buttons, inputs, icons) — WCAG AA |
309
- | **7 : 1** | Any text — WCAG AAA |
310
-
311
- **Rules of thumb for this palette:**
312
-
313
- - **White text on a colored background** — use step **600 or darker**. Steps 500 and below are typically too light (3–3.5 : 1 ratio).
314
- - **Colored text on white** — use step **700 or darker** for normal text.
315
- - **Warning (amber-500)** — always pair with `--color-text-on-warning` (gray-900). Never white text on amber-500.
316
- - **Decorative only** — any step is fine when color carries no information (icons, borders, illustrations).
317
-
318
- ### Dark theme
319
-
320
- `tokens/themes/dark.json` re-declares 13 semantic color tokens — backgrounds, border, text, `--form-color-background`, and `--color-shadow`, which flips to white. The generated `dist/css/themes/dark.css` wraps them, still inside `@layer tokens`:
321
-
322
42
  ```css
323
- @media (prefers-color-scheme: dark) {
324
- :root:not([data-color-scheme="light"]) { /* */ }
325
- }
326
- ```
327
-
328
- So the dark scheme follows the OS setting, and `data-color-scheme="light"` on `<html>` opts a page out of it. There is no forced-dark selector — the package never turns dark on a light OS. The theme comes with the full `index.css`; importing `css/semantic.css` alone leaves it out.
329
-
330
- ### Adding a custom hue
331
-
332
- Add a new primitive scale in `tokens/primitive/color.json`, following the existing pattern — one DTCG color object per step:
333
-
334
- ```json
335
- {
336
- "color": {
337
- "coral": {
338
- "50": { "$value": { "colorSpace": "oklch", "components": [0.975, 0.014, 35.0] }, "$type": "color" },
339
- "100": { "$value": { "colorSpace": "oklch", "components": [0.948, 0.032, 35.0] }, "$type": "color" },
340
- "950": { "$value": { "colorSpace": "oklch", "components": [0.225, 0.078, 35.0] }, "$type": "color" }
341
- }
342
- }
343
- }
43
+ --color-sienna-600: oklch(0.53 0.195 22); /* primitive: what is the value? */
44
+ --color-brand: var(--color-sienna-600); /* semantic: what is it for? */
45
+ --btn-color-background: var(--color-brand); /* component: where is it used? */
344
46
  ```
345
47
 
346
- Run `npm run build`, then reference the generated `--color-coral-*` from `tokens/semantic/color.json` or from your project's own `@layer tokens` override.
347
-
348
- ---
349
-
350
- ## Customization
351
-
352
- Two approaches are available depending on how deep the override needs to go.
353
-
354
- ### 1 — CSS override (recommended)
355
-
356
- All tokens live in `@layer tokens`, the lowest-priority layer in the stack. Any `@layer tokens` block imported **after** this package wins by source order — no specificity tricks needed.
48
+ Overriding the semantic layer is how a project rebrands without forking:
357
49
 
358
50
  ```css
359
51
  @import '@uncinq/design-tokens';
360
52
 
361
53
  @layer tokens {
362
54
  :root {
363
- --color-brand: var(--color-violet-600);
364
- --color-brand-muted: var(--color-violet-100);
365
- --color-brand-hover: var(--color-violet-700);
366
- --color-brand-strong: var(--color-violet-900);
367
- --font-family-sans: 'Inter', system-ui, sans-serif;
55
+ --color-brand: var(--color-violet-600);
56
+ --color-brand-hover: var(--color-violet-700);
368
57
  }
369
58
  }
370
59
  ```
371
60
 
372
- This covers most use cases: brand color, typography, spacing tweaks, component-level tokens.
61
+ ## At a glance
373
62
 
374
- MDN: [Using CSS cascade layers](https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Styling_basics/Cascade_layers)
63
+ - **19 hues** at 11 steps each, all in OKLCH, plus black and white
64
+ - **661 tokens** across 23 source files
65
+ - **CSS output only**, because custom properties are the one format that works unchanged everywhere
66
+ - **Dark theme** as a 13-token overlay, following the OS setting
375
67
 
376
- ### 2 — JSON + build in the consuming project
68
+ ## Documentation
377
69
 
378
- The package exports its raw JSON source files (`./tokens/*`). A project can source them directly in its own [Style Dictionary](https://styledictionary.com/) config alongside project-specific token files:
70
+ Full documentation: **[socle.uncinq.dev/docs/design-tokens/](https://socle.uncinq.dev/docs/design-tokens/)**
379
71
 
380
- ```js
381
- // style-dictionary.config.js (in the consuming project)
382
- export default {
383
- source: [
384
- 'node_modules/@uncinq/design-tokens/tokens/**/*.json',
385
- 'tokens/**/*.json', // project tokens — extend or override the package
386
- ],
387
- // ...
388
- };
389
- ```
390
-
391
- Project token files that define the same path as a package token will override it during the build. New paths are additive.
392
-
393
- Use this approach to:
72
+ It is also versioned with the code in [`docs/`](docs/), and ships inside the npm package, so it is readable offline and from `node_modules`:
394
73
 
395
- - Redefine the primitive palette entirely (new brand hue, different scale)
396
- - Add semantic tokens that don't exist in the package
397
- - Generate additional output formats (JS, SCSS…)
74
+ - [Naming](docs/naming.md) the grammar, the rules, the scales, the category list
75
+ - [Colors](docs/colors.md) OKLCH, the palette, the semantic roles, WCAG guidance
76
+ - [Dark mode](docs/dark-mode.md) the overlay model and how to opt out
77
+ - [Customizing](docs/customizing.md) — the two override strategies
78
+ - [Reference](docs/reference.md) — every token, generated from the sources
79
+ - [DTCG format](docs/dtcg.md) — the authoring format
80
+ - [Style Dictionary](docs/style-dictionary.md) — the build pipeline
81
+ - [Fluid scales](docs/utopia.md) — the Utopia method
398
82
 
399
- | Need | Approach |
400
- | --- | --- |
401
- | Change brand, typography, a few tokens | CSS `@layer tokens` |
402
- | Redefine the entire primitive palette | JSON + build |
403
- | Add project-specific tokens | JSON + build (or CSS if few) |
404
-
405
- ---
406
-
407
- ## Installation
83
+ ## Build
408
84
 
409
85
  ```bash
410
- npm install @uncinq/design-tokens
411
- # or
412
- yarn add @uncinq/design-tokens
413
- ```
414
-
415
- ### Usage — CSS import
416
-
417
- ```css
418
- /* everything */
419
- @import '@uncinq/design-tokens';
420
-
421
- /* or by layer */
422
- @import '@uncinq/design-tokens/css/primitive.css';
423
- @import '@uncinq/design-tokens/css/semantic.css';
424
-
425
- /* or file by file */
426
- @import '@uncinq/design-tokens/css/primitive/color.css';
427
- @import '@uncinq/design-tokens/css/semantic/color.css';
428
- ```
429
-
430
- ### Usage — CDN (no build step)
431
-
432
- ```html
433
- <link rel="stylesheet" href="https://unpkg.com/@uncinq/design-tokens">
434
- ```
435
-
436
- ---
437
-
438
- ## File structure
439
-
440
- JSON source files (DTCG format — do not edit `dist/`):
441
-
442
- ```
443
- tokens/
444
- primitive/
445
- blur.json ← blur scale (xs → xl)
446
- color.json ← full color palette (OKLCH, 11 steps per hue)
447
- font.json ← font families, weights, sizes, line-heights
448
- shadow.json ← box-shadow scale
449
- size.json ← rem scale (--size-1 → --size-1920)
450
- semantic/
451
- blur.json ← purposeful blur aliases
452
- border.json ← border styles and widths
453
- color.json ← purposeful color aliases (--color-brand, --color-background…)
454
- focus.json ← focus ring tokens (color, style, width, offset)
455
- form.json ← form control tokens (input, label, checkbox, switch…)
456
- gradient.json ← darkening overlay gradient (colors + responsive stops)
457
- grid.json ← columns, gap, flex fractions
458
- icon.json ← SVG icon tokens (data URI)
459
- motion.json ← duration, easing, transitions
460
- opacity.json ← purposeful opacity aliases (disabled, overlay)
461
- radius.json ← border-radius scale + purposeful aliases
462
- ratio.json ← aspect-ratio values (16/9, 4/3…)
463
- shadow.json ← purposeful shadow aliases
464
- size.json ← T-shirt scale + breakpoint aliases
465
- spacing.json ← spacing scale + fluid clamp() aliases
466
- typography.json ← font-size scale (fixed + fluid), heading sizes
467
- z-index.json ← stacking order
468
- themes/
469
- dark.json ← dark color scheme overrides
86
+ npm install
87
+ npm run build # tokens/**/*.json → dist/css/**
470
88
  ```
471
89
 
472
- Generated CSS (`dist/css/` built by `npm run build`, do not edit):
473
-
474
- ```
475
- dist/css/
476
- index.css ← imports everything
477
- primitive.css ← imports all primitive files
478
- semantic.css ← imports all semantic files
479
- primitive/ ← one file per tokens/primitive/*.json
480
- semantic/ ← one file per tokens/semantic/*.json
481
- themes/ ← one file per tokens/themes/*.json
482
- ```
483
-
484
- ---
90
+ `dist/` is generated and committed. Never edit it by hand.
485
91
 
486
92
  ## References
487
93
 
488
- - [DTCG — format and concepts](docs/DTCG.md)
489
94
  - [DTCG specification](https://tr.designtokens.org/format/) — W3C Community Group draft
490
- - [Style Dictionary v5](https://styledictionary.com/) — token build pipeline, see [docs/STYLE-DICTIONARY.md](docs/STYLE-DICTIONARY.md)
491
- - [MDN: CSS cascade layers](https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Styling_basics/Cascade_layers)
95
+ - [Style Dictionary v5](https://styledictionary.com/)
96
+ - [Utopia](https://utopia.fyi) — the fluid scale method
97
+ - [`@uncinq/component-tokens`](https://github.com/uncinq/component-tokens) — the component layer
98
+ - [`@uncinq/css-base`](https://github.com/uncinq/css-base) — the CSS foundation consuming these tokens
99
+
100
+ ## License
101
+
102
+ MIT © [Un Cinq](https://uncinq.dev/)