@dataimago/tokens 0.1.0-alpha.3 → 0.1.0-alpha.30

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dataimago/tokens",
3
- "version": "0.1.0-alpha.3",
3
+ "version": "0.1.0-alpha.30",
4
4
  "description": "dataimago design tokens — canonical JSON sources plus generated TS/CSS artifacts",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -30,7 +30,10 @@
30
30
  "./frequent": "./src/frequent.json",
31
31
  "./components": "./src/components.json",
32
32
  "./css": "./dist/tokens.css",
33
- "./scss": "./dist/tokens.scss"
33
+ "./scss": "./dist/tokens.scss",
34
+ "./dtcg": "./dist/tokens.dtcg.json",
35
+ "./dtcg-w3c": "./dist/tokens.w3c.dtcg.json",
36
+ "./tokens-studio": "./dist/tokens.studio.json"
34
37
  },
35
38
  "files": [
36
39
  "src",
package/src/README.md CHANGED
@@ -1,175 +1,59 @@
1
- # dataimago Design Tokens - Developer Guide
2
-
3
- ## 🎯 Source of Truth Architecture
4
-
5
- This directory contains the **authoritative source** for all design decisions across the dataimago ecosystem. These JSON-based tokens serve as the foundation for:
6
-
7
- - **CSS Custom Properties**: Generated via idempotent build process
8
- - **Theme Support**: Automatic light/dark mode generation
9
- - **Consumer Integration**: Distributed to all consumer repositories via git submodules
10
- - **Design Consistency**: Single definition → multiple output formats
11
-
12
- ## 🔄 Idempotent Token Processing
13
-
14
- The token build system follows strict deterministic principles:
15
-
16
- - **✅ Stable Output**: Same tokens → identical CSS every time
17
- - **✅ No Timestamps**: Generated CSS excludes dynamic timestamps
18
- - **✅ Version Controlled**: Only source tokens are committed, generated files are build artifacts
19
- - **✅ Consumer Ready**: Generated assets integrate seamlessly into consumer repositories
20
-
21
- ## Overview
22
- These tokens are processed into CSS custom properties that work across light and dark themes via our idempotent build system.
23
-
24
- ## Token Structure
25
-
26
- ### 🎨 **theme-colors.json** - Theme-Aware Colors
27
- Your carefully tuned light/dark color scheme:
28
-
29
- ```json
30
- {
31
- "color": {
32
- "surface": {
33
- "page": {
34
- "light": "rgb(237, 237, 235)", // Your warm light gray
35
- "dark": "rgb(20, 20, 16)" // Your warm dark background
36
- }
37
- },
38
- "content": {
39
- "primary": {
40
- "light": "rgb(20, 20, 16)", // Near Black text on light
41
- "dark": "rgb(237, 237, 235)" // Near white on dark
42
- },
43
- "secondary": {
44
- "light": "#7c7c7c", // Your tuned light gray
45
- "dark": "#83838f" // Your tuned dark gray
46
- }
47
- }
48
- }
49
- }
50
- ```
51
-
52
- ### 🏃 **frequent.json** - High-Change Values
53
- Most commonly adjusted in DevTools:
54
-
55
- ```json
56
- {
57
- "spacing": {
58
- "component": {
59
- "padding": "1rem", // Card/button internal spacing
60
- "margin": "1.5rem", // Between-component spacing
61
- "gap": "0.75rem" // Flex/grid gaps
62
- }
63
- },
64
- "contrast": {
65
- "readable": "...", // Comfortable reading contrast
66
- "medium": "...", // Secondary information
67
- "subtle": "..." // De-emphasized text
68
- }
69
- }
70
- ```
71
-
72
- ### 🎯 **effects.json** - Theme-Aware Effects
73
- Shadows and borders that adapt to themes:
74
-
75
- ```json
76
- {
77
- "shadow": {
78
- "subtle": {
79
- "light": "0 1px 2px 0 rgb(0 0 0 / 0.05)",
80
- "dark": "0 1px 2px 0 rgb(255 255 255 / 0.03)"
81
- }
82
- },
83
- "border": {
84
- "subtle": {
85
- "light": "rgba(0, 0, 0, 0.1)",
86
- "dark": "rgba(255, 255, 255, 0.1)"
87
- }
88
- }
89
- }
90
- ```
91
-
92
- ### 🧩 **components.json** - Component References
93
- Components reference semantic tokens:
94
-
95
- ```json
96
- {
97
- "card": {
98
- "background": "surface.elevated",
99
- "padding": "spacing.component.padding",
100
- "shadow": "shadow.moderate"
101
- }
102
- }
103
- ```
1
+ # dataimago Token Source Guide
104
2
 
105
- ## DevTools → Token Workflow
3
+ This directory is the source tree for `@dataimago/tokens`. The package build turns these JSON files into CSS variables, SCSS maps, typed JS modules, and an additive DTCG-style export.
106
4
 
107
- ### Common Adjustments:
5
+ ## Distribution
108
6
 
109
- | **DevTools Change** | **Edit This Token** | **CSS Variable Generated** |
110
- |---------------------|--------------------|-----------------------------|
111
- | Card padding too tight | `frequent.json` → `spacing.component.padding` | `--spacing-component-padding` |
112
- | Text too light in dark | `theme-colors.json` → `content.secondary.dark` | `--color-content-secondary` |
113
- | Button needs more emphasis | `theme-colors.json` → `interactive.primary` | `--color-interactive-primary` |
114
- | Borders invisible | `effects.json` → `border.subtle.dark` | `--color-border-subtle` |
7
+ Consumers receive tokens through public npm packages, not a production git submodule:
115
8
 
116
- ### Quick Edit Workflow:
9
+ - House identity: `@dataimago/tokens`, `@dataimago/css`, `@dataimago/ui`, `@dataimago/brand`
10
+ - Neutral identity: `@dataimago/tokens-neutral`, `@dataimago/css-neutral`
117
11
 
118
- ```bash
119
- # 1. Edit token JSON file
120
- edit ui/src/tokens/frequent.json
121
-
122
- # 2. Quick rebuild
123
- cd ui && npm run watch # Auto-rebuilds on save
12
+ The compatibility contract for this tightening iteration is strict: do not remove existing package names, package exports, token names, CSS custom properties, or required consumer import paths.
124
13
 
125
- # 3. Changes appear instantly in browser
126
- ```
14
+ ## Source Files
127
15
 
128
- ## Generated CSS Structure
16
+ | File | Role | Emits CSS variables? | Schema-governed? |
17
+ |---|---|---:|---:|
18
+ | `colors.json` | Primitive color scales and functional colors | Yes | Yes |
19
+ | `theme-colors.json` | Semantic light/dark color roles | Yes | Yes |
20
+ | `typography.json` | Font families, sizes, weights, styles, features, line heights | Yes | Yes |
21
+ | `spacing.json` | Spacing, radius, and layout scale | Yes | Yes |
22
+ | `effects.json` | Theme-aware borders/shadows and motion tokens | Yes | Yes |
23
+ | `frequent.json` | High-change reference values and metadata clusters | No | No |
24
+ | `components.json` | Component-level aliases/reference manifest | No | No |
129
25
 
130
- The build system creates theme-aware CSS custom properties:
26
+ `frequent.json` and `components.json` are intentionally treated as metadata/reference manifests in the current alpha line. Do not assume they emit CSS or normalize them opportunistically; any migration to canonical token shape needs to preserve existing exports and CSS variables.
131
27
 
132
- ```css
133
- /* Theme-agnostic values */
134
- :root {
135
- --color-brand-dataimago-primary: #3498DB;
136
- --spacing-component-padding: 1rem;
137
- }
28
+ ## Build Outputs
138
29
 
139
- /* Light theme */
140
- :root, [data-bs-theme="light"] {
141
- --color-surface-page: rgb(237, 237, 235);
142
- --color-content-primary: #000000;
143
- }
30
+ Run from the repo root:
144
31
 
145
- /* Dark theme */
146
- [data-bs-theme="dark"], @media (prefers-color-scheme: dark) {
147
- --color-surface-page: rgb(20, 20, 16);
148
- --color-content-primary: rgb(237, 237, 235);
149
- }
32
+ ```bash
33
+ node packages/tokens/build.mjs
150
34
  ```
151
35
 
152
- ## Token Naming Convention
36
+ The build emits:
153
37
 
154
- **Pattern**: `category-purpose-variant`
38
+ - `packages/tokens/dist/tokens.css`
39
+ - `packages/tokens/dist/tokens.scss`
40
+ - `packages/tokens/dist/index.mjs`
41
+ - `packages/tokens/dist/index.cjs`
42
+ - `packages/tokens/dist/index.d.ts`
43
+ - `packages/tokens/dist/tokens.dtcg.json`
155
44
 
156
- - `--color-surface-page` = Color for surface/page level
157
- - `--color-content-primary` = Color for content/primary emphasis
158
- - `--spacing-component-padding` = Spacing for component/padding use
159
- - `--shadow-moderate` = Shadow for moderate elevation
45
+ Run the compatibility check after token changes:
160
46
 
161
- ## Theme Philosophy
162
-
163
- - **Semantic naming** = Describes purpose, not appearance
164
- - **Your colors preserved** = Light/dark values from your tuned SCSS files
165
- - **DevTools friendly** = Easy to find the token you need to change
166
- - **Automatic theming** = Components work in both themes without extra code
47
+ ```bash
48
+ node tools/check-css-vars.mjs
49
+ ```
167
50
 
168
- ## Integration with Existing System
51
+ The check compares generated CSS variable names against `packages/tokens/schema/css-vars.snapshot.json` and fails on removals. Additive variables are allowed.
169
52
 
170
- - **Quarto themes** continue working (website-light.scss, website-dark.scss)
171
- - **New tokens** complement existing system
172
- - **Backward compatible** = Old CSS still works during transition
173
- - **Build system** automatically distributes to all channels
53
+ ## Editing Rules
174
54
 
175
- Your carefully tuned color relationships are now systematized and ready for efficient DevTools-driven development! 🎯
55
+ - Use canonical leaf shapes in CSS-emitting files: `{ "value": "..." }` or `{ "light": "...", "dark": "..." }`.
56
+ - Use `_invariant` or another underscore-prefixed metadata key for group-level notes.
57
+ - Never add a group-level `description` beside string-valued children in CSS-emitting files; that is the historical walker-bailout bug pattern.
58
+ - Prefer semantic roles over primitive palette references in consumers.
59
+ - Record threshold or role changes in `wiki/log.md`, and add or amend an ADR when the change alters durable design intent.
package/src/colors.json CHANGED
@@ -40,7 +40,7 @@
40
40
  "paper": {
41
41
  "50": { "value": "#fefdfb", "description": "Paper scale — lightest warm surface; renamed from cream — reserved for elevated cards/modals when warm tint is desired" },
42
42
  "100": { "value": "#fdf9f2", "description": "Paper scale — warm page-background option (legacy cream-100); not the primary surface in this iteration" },
43
- "200": { "value": "#faf2e3", "description": "Paper scale — code-block and pull-quote background; warm tint reads as 'paper'" },
43
+ "200": { "value": "#faf2e3", "description": "Paper scale — pull-quote background; warm tint reads as 'paper' (code blocks and sunken surfaces moved to the card colour, 2026-11-02)" },
44
44
  "300": { "value": "#f5e8cf", "description": "Paper scale — call-out / emphasised panel background" },
45
45
  "400": { "value": "#edd9b3", "description": "Paper scale — muted warm accent" },
46
46
  "500": { "value": "#e0c088", "description": "Paper scale — strong warm accent; wheat" }
@@ -58,10 +58,12 @@
58
58
  "900": { "value": "#612b16", "description": "Copper scale — deep foundation" }
59
59
  },
60
60
  "accent": {
61
- "50": { "value": "#fdf2f2", "description": "Accent scale — faint wash for emancipation-coded panels" },
62
- "500": { "value": "#b54a27", "description": "Accent scale — canonical moral/emancipation accent" },
63
- "600": { "value": "#9a3e20", "description": "Accent scale — hover on accent" },
64
- "700": { "value": "#7d321a", "description": "Accent scale — pressed state" }
61
+ "50": { "value": "#f0f8fc", "description": "Accent scale — pale wash for accent-tinted backgrounds (iteration-2; was #fdf2f2 emancipation-coded panels in iteration-1)" },
62
+ "300": { "value": "#3498DB", "description": "Accent scale — dark-mode canonical (5.41:1 on stone-900, AA). Sourced from presentation-blue-500 — Flat-UI peter-river. Iteration-2 introduces this stop to enable mode-aware role mapping; see wiki/decisions/iteration-2-blue-accent.md." },
63
+ "400": { "value": "#2980B9", "description": "Accent scale — dark-mode hover/emphasized variant (sourced from presentation-blue-600 — Flat-UI belize-hole)" },
64
+ "500": { "value": "#1f618d", "description": "Accent scale — light-mode canonical (5.68:1 on stone-100, AA; 6.66:1 white-on-color, AA). Sourced from presentation-blue-700. Iteration-2 sky-blue moral-weight; supersedes iteration-1's #b54a27 emancipation-copper-red. The scale-name is preserved (consumer-side text-accent-500 keeps working with the same mental model); only the value moved." },
65
+ "600": { "value": "#154d6f", "description": "Accent scale — light-mode hover (HSL-interpolated from accent-500: H≈205°, S+4, L−6)" },
66
+ "700": { "value": "#0f3a52", "description": "Accent scale — light-mode pressed/active (HSL-interpolated from accent-500: H≈205°, S+8, L−13)" }
65
67
  },
66
68
  "presentation-blue": {
67
69
  "50": { "value": "#f0f8fc", "description": "Presentation-blue scale — pale wash for reveal.js callout backgrounds" },
@@ -72,20 +74,20 @@
72
74
  },
73
75
  "functional": {
74
76
  "success": {
75
- "value": "#27AE60",
76
- "description": "Success states and positive actions"
77
+ "value": "#009E73",
78
+ "description": "Success hue (Okabe-Ito bluish-green, 2026-11-02; was Flat-UI #27AE60). For text use the mode-aware color.state.success"
77
79
  },
78
80
  "warning": {
79
- "value": "#F39C12",
80
- "description": "Warning states and caution"
81
+ "value": "#E69F00",
82
+ "description": "Warning hue (Okabe-Ito orange, 2026-11-02; was Flat-UI #F39C12). For text use the mode-aware color.state.warning"
81
83
  },
82
84
  "error": {
83
- "value": "#E74C3C",
84
- "description": "Error states and critical issues"
85
+ "value": "#ef5350",
86
+ "description": "Error hue (red, 2026-11-02; was Flat-UI #E74C3C). For text use the mode-aware color.state.error"
85
87
  },
86
88
  "info": {
87
89
  "value": "#3498DB",
88
- "description": "Informational content"
90
+ "description": "Info hue (the slate accent). For text use the mode-aware color.state.info"
89
91
  }
90
92
  }
91
93
  }
@@ -0,0 +1,115 @@
1
+ {
2
+ "color": {
3
+ "dataviz": {
4
+ "okabe-ito": {
5
+ "orange": {
6
+ "value": "#E69F00",
7
+ "description": "Okabe-Ito orange (Okabe & Ito 2008, colour-blind safe). House data-viz primitive; maintainer decision 2026-10-29."
8
+ },
9
+ "sky-blue": {
10
+ "value": "#56B4E9",
11
+ "description": "Okabe-Ito sky blue (Okabe & Ito 2008, colour-blind safe). House data-viz primitive; maintainer decision 2026-10-29."
12
+ },
13
+ "bluish-green": {
14
+ "value": "#009E73",
15
+ "description": "Okabe-Ito bluish green (Okabe & Ito 2008, colour-blind safe). House data-viz primitive; maintainer decision 2026-10-29."
16
+ },
17
+ "yellow": {
18
+ "value": "#F0E442",
19
+ "description": "Okabe-Ito yellow — 1.13:1 on the light page: never use it without a mark outline or a label (Okabe & Ito 2008, colour-blind safe). House data-viz primitive; maintainer decision 2026-10-29."
20
+ },
21
+ "blue": {
22
+ "value": "#0072B2",
23
+ "description": "Okabe-Ito blue (Okabe & Ito 2008, colour-blind safe). House data-viz primitive; maintainer decision 2026-10-29."
24
+ },
25
+ "vermillion": {
26
+ "value": "#D55E00",
27
+ "description": "Okabe-Ito vermillion (Okabe & Ito 2008, colour-blind safe). House data-viz primitive; maintainer decision 2026-10-29."
28
+ },
29
+ "reddish-purple": {
30
+ "value": "#CC79A7",
31
+ "description": "Okabe-Ito reddish purple (Okabe & Ito 2008, colour-blind safe). House data-viz primitive; maintainer decision 2026-10-29."
32
+ },
33
+ "black": {
34
+ "light": "#000000",
35
+ "dark": "#FDF9F2",
36
+ "description": "Okabe-Ito black (Okabe & Ito 2008). In dark mode it becomes content.primary.dark: #000000 is 1.14:1 on the dark page. Dark value approved by the maintainer 2026-10-29 (dataviz-check --propose-dark)."
37
+ }
38
+ },
39
+ "categorical": {
40
+ "1": {
41
+ "value": "#E69F00",
42
+ "description": "= okabe-ito.orange (slot 1, Wilke order). Categorical colour is never the only channel: pair it with marker shape, line style or a label."
43
+ },
44
+ "2": {
45
+ "value": "#56B4E9",
46
+ "description": "= okabe-ito.sky-blue (slot 2, Wilke order). Categorical colour is never the only channel: pair it with marker shape, line style or a label."
47
+ },
48
+ "3": {
49
+ "value": "#009E73",
50
+ "description": "= okabe-ito.bluish-green (slot 3, Wilke order). Categorical colour is never the only channel: pair it with marker shape, line style or a label."
51
+ },
52
+ "4": {
53
+ "value": "#F0E442",
54
+ "description": "= okabe-ito.yellow (slot 4, Wilke order). Categorical colour is never the only channel: pair it with marker shape, line style or a label."
55
+ },
56
+ "5": {
57
+ "value": "#0072B2",
58
+ "description": "= okabe-ito.blue (slot 5, Wilke order). Categorical colour is never the only channel: pair it with marker shape, line style or a label."
59
+ },
60
+ "6": {
61
+ "value": "#D55E00",
62
+ "description": "= okabe-ito.vermillion (slot 6, Wilke order). Categorical colour is never the only channel: pair it with marker shape, line style or a label."
63
+ },
64
+ "7": {
65
+ "value": "#CC79A7",
66
+ "description": "= okabe-ito.reddish-purple (slot 7, Wilke order). Categorical colour is never the only channel: pair it with marker shape, line style or a label."
67
+ },
68
+ "8": {
69
+ "light": "#000000",
70
+ "dark": "#FDF9F2",
71
+ "description": "= okabe-ito.black (slot 8, Wilke order). Categorical colour is never the only channel: pair it with marker shape, line style or a label."
72
+ }
73
+ },
74
+ "uncertainty": {
75
+ "outer": {
76
+ "light": "#D6D6D6",
77
+ "dark": "#333333",
78
+ "description": "Outermost nested uncertainty band (gray 0.84 in the LIwLD PSTricks figures). The ramp is mirrored in dark mode so the innermost band stays the strongest. Dark value approved by the maintainer 2026-10-29 (dataviz-check --propose-dark)."
79
+ },
80
+ "union": {
81
+ "light": "#9E9E9E",
82
+ "dark": "#6B6B6B",
83
+ "description": "Union band (gray 0.62); mirrored in dark mode. Dark value approved by the maintainer 2026-10-29 (dataviz-check --propose-dark)."
84
+ },
85
+ "inner": {
86
+ "light": "#333333",
87
+ "dark": "#D6D6D6",
88
+ "description": "Innermost band (gray 0.20); mirrored in dark mode, where #333333 would be 1.46:1. Dark value approved by the maintainer 2026-10-29 (dataviz-check --propose-dark)."
89
+ }
90
+ },
91
+ "sgpc-bucket": {
92
+ "very-low": {
93
+ "value": "#D55E00",
94
+ "description": "= okabe-ito.vermillion. SGPc growth bucket 1 of 5 (very low) on the ordered scale very low → very high. Colour is never the only channel: pair it with a marker and the bucket letter code. Author decision 2026-11-01, matching the LIwLD paper's figures."
95
+ },
96
+ "low": {
97
+ "value": "#E69F00",
98
+ "description": "= okabe-ito.orange. SGPc growth bucket 2 of 5 (low) on the ordered scale very low → very high. Colour is never the only channel: pair it with a marker and the bucket letter code. Author decision 2026-11-01, matching the LIwLD paper's figures."
99
+ },
100
+ "typical": {
101
+ "value": "#56B4E9",
102
+ "description": "= okabe-ito.sky-blue. SGPc growth bucket 3 of 5 (typical) on the ordered scale very low → very high. Colour is never the only channel: pair it with a marker and the bucket letter code. Author decision 2026-11-01, matching the LIwLD paper's figures."
103
+ },
104
+ "high": {
105
+ "value": "#009E73",
106
+ "description": "= okabe-ito.bluish-green. SGPc growth bucket 4 of 5 (high) on the ordered scale very low → very high. Colour is never the only channel: pair it with a marker and the bucket letter code. Author decision 2026-11-01, matching the LIwLD paper's figures."
107
+ },
108
+ "very-high": {
109
+ "value": "#0072B2",
110
+ "description": "= okabe-ito.blue. SGPc growth bucket 5 of 5 (very high) on the ordered scale very low → very high. Colour is never the only channel: pair it with a marker and the bucket letter code. Author decision 2026-11-01, matching the LIwLD paper's figures."
111
+ }
112
+ }
113
+ }
114
+ }
115
+ }
package/src/effects.json CHANGED
@@ -18,14 +18,14 @@
18
18
  },
19
19
  "border": {
20
20
  "subtle": {
21
- "light": "rgba(20, 20, 16, 0.1)",
22
- "dark": "rgba(237, 237, 235, 0.1)",
23
- "description": "Subtle borders - element separation"
21
+ "light": "rgba(20, 20, 16, 0.47)",
22
+ "dark": "rgba(237, 237, 235, 0.47)",
23
+ "description": "Subtle borders - element separation. THE ALPHA IS THE ROLE. Distinct from color.border.subtle: this family has its own base (20,20,16 / 237,237,235), so it needs a DIFFERENT alpha to render the same. 0.47 here matches 0.45 there at 3.07:1 on the worst surface; copying 0.45 would land at 2.90:1 and fail WCAG 1.4.11. Gated by tools/contrast-check.mjs."
24
24
  },
25
25
  "moderate": {
26
- "light": "rgba(20, 20, 16, 0.15)",
27
- "dark": "rgba(237, 237, 235, 0.15)",
28
- "description": "Moderate borders - defined boundaries"
26
+ "light": "rgba(20, 20, 16, 0.63)",
27
+ "dark": "rgba(237, 237, 235, 0.63)",
28
+ "description": "Moderate borders - defined boundaries. 0.63 here matches color.border.moderate 0.60 in rendered contrast; see border.subtle on why the numbers differ between the two families."
29
29
  },
30
30
  "focus": {
31
31
  "light": "#3498DB",
@@ -51,4 +51,4 @@
51
51
  "description": "Reserved for the dataimago wordmark / brand-mark transitions; do not borrow for general UI"
52
52
  }
53
53
  }
54
- }
54
+ }