Color Theming & Design Tokens Standard
Field | Value |
|---|---|
Document type | Engineering Standard |
Applies to | Angular applications (frontend) |
Status | Active |
Token format | W3C Design Tokens Community Group (DTCG), Stable — 2025-10 |
Build tool | Style Dictionary v4 |
Owner | Frontend Team |
1. Purpose
This document defines the mandatory approach for implementing color theming (light/dark and any future themes) in Angular applications. It replaces ad-hoc SCSS variable lists with a token-driven architecture that:
separates design intent (what a color means, e.g. "danger") from design values (what a color is, e.g.
#ea0079);allows runtime theme switching without recompiling application CSS;
gives designers a structured, visual way to change colors without touching source code;
catches naming/reference mistakes at build time, not in production.
Compliance with this standard is mandatory for all new frontend modules and recommended for legacy modules undergoing refactor.
Keywords MUST, MUST NOT, SHOULD, SHOULD NOT, MAY are used per RFC 2119.
2. Scope
This standard covers:
the token architecture (reference / semantic / component layers);
the source-of-truth file format (DTCG JSON);
the build pipeline that generates CSS, SCSS, TypeScript and documentation artifacts from token sources;
the runtime mechanism for theme switching in the browser;
the collaboration workflow between designers (Figma) and engineers (Git-based code review);
governance rules enforced via linting and CI.
This standard does not cover typography, spacing, or motion tokens, although the same architecture SHOULD be reused for those domains.
3. Definitions
Term | Definition |
|---|---|
Design Token | A named, single source of truth for a design decision (e.g. a color), stored as data rather than hard-coded in a stylesheet. |
Reference Token | The raw palette value (e.g. |
Semantic Token | A token named after its purpose (e.g. |
Component Token | An optional, narrowly-scoped token for a single component's exception (e.g. |
DTCG | Design Tokens Community Group format — the W3C-track JSON standard for representing design tokens ( |
Style Dictionary | The build tool that transforms token JSON into platform-specific outputs (CSS, SCSS, TS, Markdown). |
Theme | A named set of Reference Token values (e.g. |
4. Architecture Overview
Tokens are organized in three layers. Components MUST consume the Semantic layer only; the Reference layer MUST NOT be referenced directly from component stylesheets (enforced by lint rule, see §13).
4.1 Reference Tokens
Raw palette values only (
clr.secondary.1…clr.secondary.10, etc.).MUST have identical key structure across all themes (
tokens/light/*.json,tokens/dark/*.json) — the same key MUST exist in every theme file with a theme-appropriate value.MUST NOT carry semantic meaning in the name (no
clr.danger, onlyclr.warn.6).
4.2 Semantic Tokens
Named after purpose, not appearance (
surface, notwhite).MUST alias a Reference Token via
{group.subgroup.index}syntax.SHOULD carry a
$descriptionexplaining intended usage.Is the only layer application code is allowed to consume.
4.3 Component Tokens (optional)
Used only when a single component needs a value that does not fit any existing Semantic Token and reuse elsewhere is not expected.
MUST still alias a Semantic Token (never a Reference Token directly).
SHOULD be kept local to the component's SCSS file, not in the shared token pipeline, unless reused by 2+ components.
5. Repository Structure
5.1 Rules
tokens/**/*.jsonfiles MUST be treated as the only source of truth for color values. Generated files (_reference-*.css,_semantic.scss,color-tokens.ts,color-tokens.md) MUST carry anAUTOGENERATEDheader comment and MUST NOT be hand-edited.style-dictionary.config.mjsMUST resolve all file paths relative to its own location (import.meta.url), never toprocess.cwd(), so that the build behaves identically regardless of the invoking directory.
6. Token File Format (DTCG)
All token source files MUST use the W3C DTCG format (stable specification, 2025-10). Legacy Style Dictionary format (value/comment) MUST NOT be used in new files.
tokens/light/clr.json — Reference layer, one file per theme:
tokens/semantic/semantic.json — Semantic layer, alias-only:
6.1 Rules
Every semantic token's
$valueMUST be an alias in the form{group.subgroup.index}— literal hex values in the semantic layer are FORBIDDEN and MUST fail the build (see §8.1).$type: "color"MUST be set for every color token to enable type-aware tooling (Tokens Studio, contrast checkers, IDE plugins).$descriptionSHOULD be present for every semantic token; it is surfaced in the generated documentation (§11) and in code comments.
7. Build Pipeline (Style Dictionary)
A single Node.js script (style-dictionary.config.mjs) drives four parallel build outputs from the same token sources.
7.1 Alias validation (build-time safety)
The custom SCSS/TS formats MUST throw a build error if a semantic token's $value is not a valid {alias} reference:
A typo in an alias path (e.g. {clr.secondar.1}) MUST cause the build to fail with Reference Errors: Some token references could not be found — this is a hard requirement, not an optional lint warning.
7.2 npm scripts
prebuild MUST run before every ng build/ng serve invocation so that generated artifacts can never go stale relative to token sources.
8. Runtime Theme Switching
Theme switching happens entirely in the browser via CSS Custom Properties — no application rebuild or SCSS recompilation is required to change the active theme.
8.1 Rules
Theme selection MUST be expressed as a class on
<body>(theme_light/theme_dark), not via[data-theme]attribute or inline styles, for consistency with the generated CSS selectors.To avoid a flash of the wrong theme on load (FOUC), the persisted theme preference MUST be applied to
<body>by an inline script inindex.html, executed before Angular bootstraps.New themes (e.g.
theme_high_contrast) MUST reuse the same Semantic Token names; only a newtokens/<theme-name>/clr.jsonfile and a corresponding Style Dictionary build target are required — no changes to component code.
9. Consuming Tokens in Angular Components
9.1 SCSS (preferred for styling)
9.2 TypeScript (for Canvas, Charts, inline styles)
9.3 Rules
Components MUST import tokens via
@use "styles/tokens/semantic".Components MUST NOT reference
var(--clr-*)(Reference layer) directly in component stylesheets. This is enforced by a stylelint rule (§13).Components MUST NOT hard-code hex colors in
.scss/.tsfiles outside of the token source (tokens/**/*.json).
10. Generated Documentation
Every npm run tokens:build regenerates docs/color-tokens.md — a human-readable table of all Semantic Tokens with resolved color swatches for every theme, side by side, plus the intended usage description.
SCSS variable | CSS custom property | Light | Dark | Purpose |
|---|---|---|---|---|
|
|
|
| Card and page background |
|
|
|
| Errors, destructive actions |
This file MUST be treated as read-only documentation (regenerated, not edited) and SHOULD be linked from the project README and any Storybook "Colors" page.
11. Designer Collaboration Workflow
Designers MUST NOT edit token JSON files directly. All design-side changes flow through Figma + Tokens Studio plugin, which provides a visual UI (color pickers, theme switches) over the same DTCG token structure and handles serialization back to JSON.
11.1 Rules
The Figma project MUST be configured to use the W3C DTCG token format (Tokens Studio settings → Token Format), matching the repository's format exactly.
Multi-file sync (separate
light.json/dark.json/semantic.jsonfiles matching the repository layout) requires a Tokens Studio Pro license (Multi-file Sync to Remote Storage). Teams without a Pro license MUST use Token Sets within a singletokens.jsonand add a pre-build step that splits it into the repository's file layout.All token changes from design MUST arrive as a Pull Request and MUST go through standard code review before merge — no direct pushes to the default branch.
12. Governance & Enforcement
12.1 Stylelint rule (mandatory)
The Reference layer (var(--clr-*)) MUST NOT be used directly in component stylesheets. This is enforced automatically:
An overrides exemption MUST be scoped only to files inside src/styles/tokens/ (the generated Reference/Semantic layer itself).
12.2 CI drift check (mandatory)
CI MUST fail if generated artifacts do not match what the current token sources would produce — this catches cases where a token source was edited but the build was not re-run before commit:
12.3 Contrast validation (recommended)
A WCAG contrast check SHOULD run in CI for critical semantic pairs (e.g. text-primary on surface) to prevent accessibility regressions introduced by a palette change:
13. Versioning & Change Management
Breaking changes to Semantic Token names (rename/removal) MUST be communicated to all consuming teams before merge, since component code references these names directly.
Reference Token value changes (palette tuning) are non-breaking for component code (aliases stay valid) but MAY change the visual contrast of the affected theme — the CI contrast check (§12.3) is the safety net for this case.
Adding a new theme (e.g.
theme_high_contrast) is additive and MUST NOT require changes to Semantic Token names or component code — only a newtokens/<theme>/clr.jsonand a new Style Dictionary build target.
14. Appendix A — Migrating Legacy (non-DTCG) Token Files
If existing token files use the legacy Style Dictionary format (value/comment), they MUST be migrated to DTCG before being adopted under this standard. Use the provided migration script (design-tokens/tools/migrate-to-dtcg.mjs), then:
add
usesDtcg: trueto everyStyleDictionaryinstance instyle-dictionary.config.mjs;update custom formats to read
token.original.$value(raw alias) andtoken.$value(resolved value) instead of the unprefixedvalue/commentfields;re-run
npm run tokens:buildand diff the generated artifacts against the pre-migration output — the diff SHOULD be empty aside from JSON key ordering.
15. Appendix B — Glossary
Term | Meaning |
|---|---|
Reference Token | Raw palette value, internal implementation detail. |
Semantic Token | Purpose-named token; the public API for component styling. |
Component Token | Narrow, component-scoped exception aliasing a Semantic Token. |
Alias | A |
DTCG | W3C Design Tokens Community Group JSON format. |
FOUC | Flash Of Unstyled/wrong-themed Content on initial page load. |