Skip to content

chore: design system colour tokens, primitives & Storybook#6883

Open
talissoncosta wants to merge 15 commits intomainfrom
chore/design-system-tokens
Open

chore: design system colour tokens, primitives & Storybook#6883
talissoncosta wants to merge 15 commits intomainfrom
chore/design-system-tokens

Conversation

@talissoncosta
Copy link
Copy Markdown
Contributor

@talissoncosta talissoncosta commented Mar 9, 2026

  • I have read the Contributing Guide.
  • I have added information to docs/ if required so people know about the feature.
  • I have filled in the "Changes" section below.
  • I have filled in the "How did you test this code" section below.

Changes

Contributes to #6606

Design system token foundation with Storybook, Chromatic visual regression, and MCP integration for AI-assisted development.

1. Token architecture

Single source of truth: common/theme/tokens.json defines all tokens with values, dark mode overrides, and usage descriptions. A codegen script (scripts/generate-tokens.mjs) generates four output files — tokens.ts, _tokens.scss, _token-utilities.scss, and a flat JSX MCP reference story. lint-staged auto-runs the codegen on commit.

Primitive → Semantic reference chain:

  • Primitives defined once as CSS custom properties (77 colours across 7 families + slate-1000)
  • Semantic tokens reference primitives via var(--primitive) — zero raw hex in the semantic layer
  • Alpha/opacity variants use OKLCH relative colour syntax: oklch(from var(--purple-600) l c h / 0.08)
  • Changing a primitive value updates all semantic tokens that reference it

Why OKLCH? OKLCH is a perceptually uniform colour space. Its relative colour syntax lets us derive alpha variants directly from a primitive — oklch(from var(--purple-600) l c h / 0.08) keeps the same lightness, chroma, and hue but applies 8% opacity. This means changing --purple-600 automatically updates all its alpha variants. No hardcoded RGB values, no duplicate colour definitions. Browser support: Chrome 119+, Safari 16.4+, Firefox 128+ — fine for a developer tool.

Colour tokens (40): Surface, text, border, and icon categories with light/dark variants. Primitive palette (_primitives.scss) provides 7 colour families (slate, purple, red, green, gold, blue, orange) with 50–950+ tonal scales.

Non-colour tokens (18):

  • Border radius — 8 values (none through full)
  • Elevation — 4 shadow levels with dark mode overrides (OKLCH references)
  • Motion — 3 durations + 3 easing curves

Token utility classes (_token-utilities.scss): Auto-generated CSS classes consuming tokens — bg-surface-*, text-*, border-*, icon-*, rounded-*, shadow-*, transition-*.

2. Storybook + Chromatic

  • Storybook with webpack5, SWC compiler, a11y addon
  • Chromatic CI workflow captures visual regression on every PR
  • Light + dark mode snapshots for every component story via Chromatic modes
  • Storybook MCP connected — AI tools can query full component and token catalogue
  • MCP story shows primitive references (var(--purple-600)) not resolved hex values

3. Component stories

Component Coverage
Banner 4 variants, with/without CTA
Button 7 themes, 4 sizes, disabled, icons
Switch On, off, disabled, controlled
Skeleton Text, badge, circle variants
SettingRow Pattern component with React 19 useId()
Icons Categorised searchable catalogue (61 icons)

4. New components

  • Banner — variant-driven alert using semantic colour tokens
  • SettingRow — accessible settings toggle with ARIA labels
  • Skeleton — loading placeholder with reduced motion support
  • RequireFeatureOwnershipSetting — project setting (Project setting: Enforce feature ownership #4432)

5. Documentation (MDX + token stories)

  • Palette — primitive colour scales (auto-generated)
  • Semantic Colour Tokens — runtime CSS var reading with theme toggle (surface, text, border, icon categories)
  • Tag & Project Colours — categorical swatches
  • Spacing, Radius, Elevation, Motion — visual previews importing from tokens.ts
  • Token Reference (MCP) — auto-generated flat JSX with primitive references for AI
  • Decision Framework — where does a new colour go?
  • Token Maintenance — codegen workflow for adding/modifying/removing tokens

6. Dogfooding

documentation/docs.scss uses token references across all categories (spacing, colour, font, radius, motion).

How did you test this code?

  • npm run storybook — all stories render correctly in light and dark mode
  • npm run build-storybook — builds without errors
  • npm run generate:tokens — codegen produces correct output, idempotent (running twice gives same result)
  • npm run typecheck — no new type errors from token files
  • ENV=local npm run dev — app renders identically (no visual regression)
  • Chromatic CI captures light + dark snapshots for component stories
  • Storybook MCP returns component docs and token reference via get-documentation
  • lint-staged: editing tokens.json and committing auto-regenerates all output files
  • Verified: zero raw hex values in semantic colour layer, all reference primitives via var() or OKLCH

@vercel
Copy link
Copy Markdown

vercel bot commented Mar 9, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
flagsmith-frontend-preview Ready Ready Preview, Comment Apr 1, 2026 5:05pm
flagsmith-frontend-staging Ready Ready Preview, Comment Apr 1, 2026 5:05pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Ignored Ignored Preview Apr 1, 2026 5:05pm

Request Review

@github-actions github-actions bot added the front-end Issue related to the React Front End Dashboard label Mar 9, 2026
@codecov
Copy link
Copy Markdown

codecov bot commented Mar 9, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.33%. Comparing base (3caa120) to head (2ff9ae1).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #6883   +/-   ##
=======================================
  Coverage   98.33%   98.33%           
=======================================
  Files        1335     1335           
  Lines       49943    49943           
=======================================
  Hits        49113    49113           
  Misses        830      830           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@talissoncosta
Copy link
Copy Markdown
Contributor Author

Blocker: #6866 (Decouple Button from Redux store) should land before or alongside this PR — Button's dependency on AccountStore and Redux state prevents adding Storybook stories for any component that uses <Button>.

@github-actions github-actions bot added the chore label Mar 9, 2026
@talissoncosta talissoncosta linked an issue Mar 10, 2026 that may be closed by this pull request
7 tasks
@talissoncosta talissoncosta force-pushed the chore/design-system-tokens branch from 42b4c1e to 87a4eae Compare March 10, 2026 20:10
@github-actions github-actions bot added chore and removed chore labels Mar 10, 2026
@github-actions github-actions bot added chore and removed chore labels Mar 10, 2026
@github-actions github-actions bot added chore and removed chore labels Mar 10, 2026
@talissoncosta talissoncosta marked this pull request as ready for review March 10, 2026 20:47
@talissoncosta talissoncosta requested review from a team as code owners March 10, 2026 20:47
talissoncosta and others added 15 commits April 1, 2026 09:11
Single source of truth: common/theme/tokens.json defines all 109
design tokens (41 colour + 68 non-colour) with values, dark mode
overrides, and usage descriptions.

Codegen script (scripts/generate-tokens.mjs) generates:
- common/theme/tokens.ts — TypeScript exports
- web/styles/_tokens.scss — CSS custom properties (:root + .dark)
- documentation/TokenReference.generated.stories.tsx — flat JSX for MCP

Token categories:
- Colour: surface, text, border, icon (with light/dark variants)
- Spacing: Tailwind naming convention (--space-1 = 4px, --space-4 = 16px)
- Border radius: none through full (8 values)
- Typography: headings h1-h6, body, caption, label, font weights
- Elevation: 4 shadow levels with dark mode overrides
- Motion: 3 durations + 3 easing curves

Primitive colour palette (_primitives.scss) provides 7 families
(slate, purple, red, green, gold, blue, orange) with 50-950 scales.

lint-staged auto-runs codegen when tokens.json is committed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Set up Storybook 10 with webpack5, SWC compiler, and a11y addon.
Chromatic CI workflow captures visual regression on every PR.
Storybook UI respects OS colour scheme preference (light/dark).
Chromatic modes capture every component story in both themes.

Components with stories:
- Banner — 4 variants (success, warning, danger, info) with CTA
- Button — 7 themes, 4 sizes, disabled states, icon variants
- Switch — on, off, disabled, controlled
- Skeleton — text, badge, circle variants
- SettingRow — pattern component using React 19 useId()
- Icons — categorised searchable catalogue of all 61 icons

New components:
- Banner — variant-driven alert with semantic colour tokens
- SettingRow — accessible settings toggle with ARIA labels
- Skeleton — loading placeholder with reduced motion support
- RequireFeatureOwnershipSetting — project setting (#4432)

Shared Storybook utilities:
- DocPage, ScaleRow, Swatch, TokenGroup helper components
- docs.scss dogfooding 79 token references (spacing, colour, font,
  radius, motion)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Visual stories for each token category:
- Palette — primitive colour scales (auto-generated from _primitives.scss)
- Semantic Colour Tokens — runtime CSS var reading with theme toggle
- Tag & Project Colours — categorical swatches
- Spacing, Border Radius, Elevation, Motion — import from tokens.ts

Token Reference (MCP) — auto-generated flat JSX with all 109 tokens
inlined for Storybook MCP consumption by AI agents.

All documentation stories have Chromatic snapshots disabled.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Introduction — welcome page with getting started guide
- Decision Framework — where does a new colour go? + how to create
  a semantic token (HTML tables for MDX3 compat)
- Token Maintenance — codegen workflow, adding/modifying/removing tokens
- Typography — token reference for --font-* tokens (audit findings
  moved to Notion/Slides, issue #7077 for future components)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add _token-utilities.scss with utility classes consuming the design
tokens for colours, borders, icons, radius, shadows, font weights, and
transitions. These fill the gap Bootstrap doesn't cover — semantic
surface colours, icon colours, border radius tokens, etc.

Remove spacing tokens entirely — Bootstrap handles spacing via its
existing utility classes. This avoids two competing sources of truth
for the same concern.

- Create web/styles/_token-utilities.scss (no !important, no spacing)
- Remove space key from tokens.json
- Update generate-tokens.mjs to skip spacing generation
- Delete SpacingTokens.stories.tsx
- Regenerate _tokens.scss, tokens.ts, and MCP reference story
- Update TokenMaintenance.mdx and docs.scss

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add utility class generation to the codegen pipeline. When tokens.json
changes, the pre-commit hook now generates _token-utilities.scss
alongside _tokens.scss, tokens.ts, and the MCP reference story.

Adding a new token to tokens.json automatically creates its utility
class — no manual SCSS to write.

- Add generateUtilities() to generate-tokens.mjs
- Update lint-staged to auto-stage _token-utilities.scss
- Update TokenMaintenance.mdx to document the 4-file pipeline

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The text-on-fill token was the only token that described a surface
context rather than a semantic role, breaking the consistent
{category}-{role} naming pattern. It also had no dark mode variant
(always #ffffff), unlike other semantic tokens.

Removed from tokens.json, _tokens.scss, _token-utilities.scss,
tokens.ts, and all documentation references.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Font tokens (family, h1–h6, body, caption, label, weights) were added
prematurely. Typography is listed as future work in the proposal and
the approach hasn't been agreed on yet. Remove from tokens.json,
generated SCSS, utility classes, and codegen script.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
These were removed from tokens.ts in a previous commit but the
barrel export in index.ts wasn't updated, causing type errors.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The lockfile had a corrupted $@types/react reference that broke
npm ci on CI. Restored from main and re-ran npm install.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add all 77 primitive colours (slate, purple, red, green, gold, blue,
orange) plus slate-1000 (#000000) to tokens.json as the single source
of truth. This enables the generator to output var() references
instead of resolved hex values in semantic tokens.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…utput

Update the token generator to:
- Output primitive CSS custom properties in :root
- Replace resolved hex values with var(--primitive) references
- Convert rgba() alpha variants to oklch(from var(--primitive) l c h / alpha)
- Show primitive references in the Storybook MCP story

Semantic tokens now trace back to primitives — zero raw hex or rgba
in the colour layer. Addresses review feedback on PR #6883.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Icon token group was missing from the ORDER array and GROUP_LABELS
map, so --color-icon-* tokens were not displayed in the Semantic
Colour Tokens story.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Storybook MCP is the source of truth for the design system. Claude
should query it before grepping source files to find components.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

chore front-end Issue related to the React Front End Dashboard

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Proposal: Introduce semantic colour tokens and primitive palette

2 participants