Skip to content

Commit ebed449

Browse files
authored
docs: add ADR 0008 — generate TS tokens from Tokens Studio exports (#5170)
* docs: add ADR 0008 — generate TS tokens from Tokens Studio exports * docs: link legacy token pipeline guide from ADR 0008
1 parent aa58325 commit ebed449

1 file changed

Lines changed: 100 additions & 0 deletions

File tree

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# Generate TypeScript tokens by combining the Tokens Studio DTCG and CSS exports
2+
3+
- **Status:** Accepted
4+
- **Date:** 2026-07-13
5+
- **Decision makers:** Frida Erdal, EDS Core Team
6+
7+
## Context
8+
9+
The new Tokens Studio pipeline replaces the legacy Figma-REST + Style Dictionary token build. The platform exports CSS, SCSS, DTCG, Figma, Swift, Android, and Compose — but **no TypeScript format**. `equinor/design-system-mobile` (React Native) consumes TypeScript token modules (semantic colours per colour scheme, typography, spacing per density), so the pipeline must produce a TS surface.
10+
11+
Two platform behaviours constrain the solution:
12+
13+
- The **DTCG export preserves `{alias}` references and unevaluated colour formulas** (`set_chroma(set_lightness(...))`). It is a structural interchange format, not resolved values.
14+
- The **CSS export is the only format that runs the platform's formula engine**, producing concrete `oklch()` values, joined across files by plain `var(--eds-*)` chains.
15+
16+
## Decision Drivers
17+
18+
- No Style Dictionary — the legacy build is being retired
19+
- React Native-compatible values: hex colours (no `oklch()`), unitless numbers
20+
- Must not reimplement the platform's colour formula engine
21+
- Runs unattended in CI (release-triggered, no CI on the resulting PR) — failures must be loud, never silently wrong output
22+
- TS values must be identical to what CSS consumers get
23+
24+
## Options Considered
25+
26+
### Option 1: Style Dictionary on the pulled raw token sets
27+
28+
Keep the legacy tooling, pointed at the Studio-pulled JSON.
29+
30+
**Pros:**
31+
32+
- Familiar tooling, existing formats
33+
34+
**Cons:**
35+
36+
- The raw token sets contain unevaluated colour formulas Style Dictionary cannot compute
37+
- Keeps alive the dependency the new pipeline exists to remove
38+
39+
### Option 2: Resolve the DTCG export in our own codegen
40+
41+
Dereference `{alias}` chains and evaluate formulas locally.
42+
43+
**Pros:**
44+
45+
- Single input, pure DTCG
46+
47+
**Cons:**
48+
49+
- Requires reimplementing Tokens Studio's colour engine (`set_chroma`, `set_lightness`, gaussian scales) — a moving target we would have to keep bug-compatible
50+
51+
### Option 3: Parse the CSS export alone
52+
53+
The CSS output has evaluated values; derive the TS structure from the custom property names.
54+
55+
**Pros:**
56+
57+
- Single input, values already evaluated
58+
59+
**Cons:**
60+
61+
- Flattened kebab-case names make tree reconstruction ambiguous (`corner-radius-rounded-outer``cornerRadius.roundedOuter` or `cornerRadius.rounded.outer`?)
62+
- No `$type` metadata to drive value conversion
63+
64+
### Option 4: The platform's resolved-tokens REST API
65+
66+
`GET /api/v1/projects/:id/resolved_tokens` returns computed values.
67+
68+
**Pros:**
69+
70+
- Purpose-built for CI consumption
71+
72+
**Cons:**
73+
74+
- Not exposed through the `studio` CLI — would need separate HTTP client and auth plumbing alongside the existing OIDC CLI flow
75+
76+
## Decision
77+
78+
**Combine both exports** (`scripts/generate-ts-tokens.mjs` in `packages/eds-tokens`, zero dependencies): the DTCG export supplies the token tree and `$type` metadata; for every leaf the script derives the CSS custom property name, dereferences the `var()` chain in the right dimension context (colour scheme × density), and converts values — `oklch()` to hex via CSS Color 4 §13.2 gamut mapping (chroma bisection, verified identical to lightningcss for every colour in the export), `px` to unitless numbers. Modules whose resolved values differ per colour scheme are split into per-scheme files automatically. Unknown `$type`s, broken `var()` chains, and unsupported value syntax fail the build.
79+
80+
This satisfies the drivers: no Style Dictionary, no reimplemented formula engine (the platform evaluates; we only convert), RN-ready values guaranteed identical to the CSS output, and loud failures for the unattended run.
81+
82+
### Consequences
83+
84+
- Good, because token values cannot drift between the CSS and TS outputs — they share one evaluation
85+
- Good, because the script has no dependencies and no coupling to retired tooling
86+
- Good, because per-scheme splitting is data-driven — new divergent dimensions surface automatically
87+
- Bad, because the codegen is pinned to the saved export configurations' shape (file layout, `eds` prefix, kebab casing) — changing those in Studio requires a matching script change
88+
- Bad, because the value parser accepts only today's CSS syntax; new value forms from the platform fail the release run until the converter learns them (intentionally loud, but requires a fix before tokens flow again)
89+
- Bad, because the gamut-mapping code must track the CSS Color 4 algorithm to stay bit-identical with browsers
90+
91+
### Confirmation
92+
93+
The release workflow (`tokens_studio_release.yaml`) runs the script on every Tokens Studio release; any deviation fails the run and alerts via the Slack step. Generated modules were verified with `tsc --noEmit --strict`, Prettier, and a lightningcss cross-check of all colour conversions.
94+
95+
## Related
96+
97+
- [`documentation/agent-instructions/TOKENS_STUDIO.md`](../agent-instructions/TOKENS_STUDIO.md) — pipeline documentation
98+
- [`documentation/how-to/TOKEN_SYSTEM_GUIDE.md`](../how-to/TOKEN_SYSTEM_GUIDE.md) — the legacy Figma-REST + Style Dictionary pipeline this replaces
99+
- [ADR-0007](./0007-token-variable-architecture-spacing-typography.md) — token variable architecture (Figma structure)
100+
- Issues [#5164](https://github.com/equinor/design-system/issues/5164), [#5108](https://github.com/equinor/design-system/issues/5108); PR [#5166](https://github.com/equinor/design-system/pull/5166)

0 commit comments

Comments
 (0)