--- name: design-tokens description: Guide for creating and maintaining design-tokens.json, the single source of styling values for Web, Flutter, and WinUI 3. Use when creating or updating design tokens. --- # Design Tokens Skill This skill explains how to create and maintain `docs/design/design-tokens.json` — the single source of truth for all styling values (color, typography, spacing, radius, shadow, motion, breakpoints). Generated platform code must read from these tokens and must never hard-code values. ## Core Principle > One token definition → many platform outputs. Never hard-code a color, size, or spacing in generated code. ## Format Use a JSON structure inspired by the Design Tokens Community Group format. Every token is an object with `$type` and `$value`: ```json { "color": { "background": { "primary": { "$type": "color", "$value": "#0F172A" } } }, "spacing": { "md": { "$type": "dimension", "$value": "16px" } } } ``` Supported `$type` values: `color`, `dimension`, `fontFamily`, `fontWeight`, `duration`, `cubicBezier`, `number`, `strokeStyle`. ## Token Groups `design-tokens.json` should include these groups (omit a group only if it truly does not apply): - **color** — semantic color tokens - **typography** — font families, sizes, weights, line heights - **spacing** — spacing scale (xs, sm, md, lg, xl, …) - **radius** — border radius scale - **shadow** / **elevation** — box-shadow / elevation tokens - **motion** — animation durations and easings - **breakpoint** — responsive breakpoints (include when `web` is a target) ## Rules ### Naming tokens - Use **semantic names**, not descriptive names. `color.text.primary` (good) vs `color.slate-900` (bad). - Use a consistent scale for numeric families: `sm`, `md`, `lg`, `xl` — or numeric `4`, `8`, `12` — pick one and stick to it. - Group by role then by emphasis: `color.background.primary`, `color.background.muted`, `color.text.primary`, `color.text.secondary`, `color.accent.primary`, `color.state.success`, `color.state.danger`. - Token names are referenced verbatim in `ui-blueprint.json` (e.g. `"padding": "lg"`). They must match exactly. ### Using semantic color names - Define colors by **role** (background, text, accent, border, state, overlay) and **emphasis** (primary, secondary, muted). - Do not expose raw hex scales as the only option. If you need a raw scale, keep it in a separate `color.palette` group and reference it from semantic tokens. - Provide both light and dark values where the app supports them: `color.background.primary` (light) and `color.background.primary-dark`, or a `dark` sub-object — pick one convention and document it in `platform-mapping.md`. ### Avoiding hard-coded values in generated code - Generated Web code uses CSS variables / Tailwind theme keys / theme objects derived from tokens. - Generated Flutter code uses `ThemeData`, `ColorScheme`, and constants derived from tokens. - Generated WinUI 3 code uses `ResourceDictionary` entries derived from tokens. - **Never** inline `#0F172A` or `16px` in generated source. Always reference the token-derived variable/resource. - If a value is needed that has no token, add the token to `design-tokens.json` first, then use it. ### Mapping tokens to platform-specific code `design-tokens.json` is platform-agnostic. The conversion to each platform is documented in `docs/design/platform-mapping.md` and performed by the **platform-ui-generation** skill. This skill only defines and maintains the tokens. ## Example ```json { "color": { "background": { "primary": { "$type": "color", "$value": "#0F172A" }, "muted": { "$type": "color", "$value": "#1E293B" } }, "text": { "primary": { "$type": "color", "$value": "#F8FAFC" }, "secondary": { "$type": "color", "$value": "#94A3B8" } }, "accent": { "primary": { "$type": "color", "$value": "#38BDF8" } }, "state": { "success": { "$type": "color", "$value": "#22C55E" }, "danger": { "$type": "color", "$value": "#EF4444" } } }, "typography": { "fontFamily": { "base": { "$type": "fontFamily", "$value": "Inter, system-ui, sans-serif" } }, "size": { "sm": { "$type": "dimension", "$value": "14px" }, "md": { "$type": "dimension", "$value": "16px" }, "lg": { "$type": "dimension", "$value": "20px" } } }, "spacing": { "sm": { "$type": "dimension", "$value": "8px" }, "md": { "$type": "dimension", "$value": "16px" }, "lg": { "$type": "dimension", "$value": "24px" } }, "radius": { "card": { "$type": "dimension", "$value": "16px" }, "pill": { "$type": "dimension", "$value": "9999px" } }, "shadow": { "card": { "$type": "shadow", "$value": "0 4px 12px rgba(0,0,0,0.15)" } }, "motion": { "duration": { "fast": { "$type": "duration", "$value": "120ms" }, "base": { "$type": "duration", "$value": "200ms" } } }, "breakpoint": { "sm": { "$type": "dimension", "$value": "640px" }, "md": { "$type": "dimension", "$value": "768px" }, "lg": { "$type": "dimension", "$value": "1024px" } } } ``` ## Maintenance Checklist When updating tokens: - [ ] JSON is valid. - [ ] Token names referenced in `ui-blueprint.json` still exist (no broken references after a rename). - [ ] New tokens follow the naming and semantic-name rules. - [ ] No duplicate tokens (same role under two names). - [ ] `platform-mapping.md` still covers how every token group maps to each target platform.