
Wire Figma Tokens into PrimeNG + Angular 20 with Storybook and Chromatic: Accessible Typography, Density, and Real CI Guardrails
A practical pipeline to turn Figma tokens into live PrimeNG/Angular components—with Signals, Storybook review, Chromatic visual diffing, and AA accessibility baked in.
Design tokens are your contract between Figma and production. Storybook and Chromatic make that contract enforceable.Back to all posts
I’ve shipped token-driven Angular systems for a telecom ads analytics platform, an airline kiosk fleet, and insurance telematics dashboards. The pattern is consistent: if tokens leave Figma but stop at a PDF, your app drifts. When tokens flow into Angular 20+ with Signals, PrimeNG, Storybook, and Chromatic, your UI stops jittering and your brand stops eroding in PRs.
As companies plan 2025 Angular roadmaps, this is the repeatable path I use at AngularUX to wire design tokens end-to-end—accessible typography, density controls, AngularUX color palette, and measurable guardrails so recruiters, PMs, and engineers can inspect change safely.
Why Figma Tokens Need a CI Loop, Not a PDF
If you want to hire an Angular developer to stabilize visual language, ask for this loop: Figma → tokens → Angular 20 Signals → Storybook → Chromatic → Firebase preview. Anything less, and teams regress visually between sprints.
Design tokens are an API
Tokens are the API from design to code. When they’re first-class in your repo, you can wire them to PrimeNG, D3/Highcharts, and Storybook docs with the same source of truth.
AA contrast, typography, and density are not vibes; they’re testable. Chromatic + Storybook + Lighthouse give you numbers, not opinions.
One export, many consumers
AA accessibility is measurable
Brand fidelity through CI
Enterprise realities I design for
I’ve done this in multi-tenant apps (broadcast scheduling, device portals) where theme inheritance and brand slices matter. Role-based dashboards choose colors/typography that communicate priority without breaking contrast.
Kiosk flows need density switches and large, legible typography for touch; offline visuals must age gracefully without jitter.
Multi-tenant themes
Role-based dashboards
Kiosk/offline tolerance
The Pipeline: Figma → PrimeNG → Storybook (with Signals)
This loop is cheap to maintain in an Nx monorepo and pays for itself when you can prove AA contrast and density budgets in PR reviews.
1) Export tokens from Figma
Keep names flat-ish and semantic: color.brand.primary.500, typography.body.md, spacing.200, radius.sm.
Tokens Studio JSON
Angular-friendly naming
2) Transform with Style Dictionary
Style Dictionary outputs CSS vars for runtime, SCSS for PrimeNG overrides, and TS types for safe usage in components.
CSS variables
SCSS maps
TS types
3) Map to PrimeNG theme variables
PrimeNG exposes CSS variables (e.g., --p-primary-color). We map AngularUX palette tokens to those and scope light/dark via .theme-light/.theme-dark on html.
Use --p-* variables
Scope by theme class
4) Runtime control with Signals/SignalStore
A small SignalStore holds theme, density, and scale. Switching applies CSS classes/vars and triggers minimal work; data-viz re-reads CSS vars.
Theme and density as signals
No re-render storms
5) Storybook + Chromatic
Stories render with token decorators; Chromatic runs visual diffs, a11y checks, and blocks merges on regressions.
Global toolbar for theme/density
Chromatic thresholds
Code: The Design Token Pipeline
{
"$schema": "https://tokens.studio/schemas/aliases.json",
"color": {
"brand": {"primary": {"500": {"value": "#4C7AF1"}, "600": {"value": "#3B64D6"}}},
"surface": {"base": {"value": "#0F1222"}, "card": {"value": "#141832"}},
"text": {"high": {"value": "#F8FAFC"}, "muted": {"value": "#98A2B3"}},
"status": {"success": {"500": {"value": "#16A34A"}}, "danger": {"500": {"value": "#DC2626"}}}
},
"typography": {
"family": {"sans": {"value": "'Inter', system-ui, -apple-system, Segoe UI, Roboto"}},
"size": {"xs": {"value": "12px"}, "sm": {"value": "14px"}, "md": {"value": "16px"}, "lg": {"value": "18px"}},
"line": {"tight": {"value": 1.25}, "normal": {"value": 1.5}}
},
"radius": {"sm": {"value": "6px"}, "md": {"value": "10px"}},
"spacing": {"100": {"value": "4px"}, "200": {"value": "8px"}, "300": {"value": "12px"}}
}// tools/style-dictionary/config.cjs
const StyleDictionary = require('style-dictionary');
module.exports = {
source: ['libs/design-tokens/src/tokens/**/*.json'],
platforms: {
css: {
transformGroup: 'css',
buildPath: 'libs/design-tokens/dist/',
files: [{ destination: 'tokens.css', format: 'css/variables' }]
},
scss: {
transformGroup: 'scss',
buildPath: 'libs/design-tokens/dist/',
files: [{ destination: '_tokens.scss', format: 'scss/map-deep' }]
},
ts: {
transformGroup: 'js',
buildPath: 'libs/design-tokens/dist/',
files: [{ destination: 'tokens.ts', format: 'javascript/module' }]
}
}
}# package.json scripts
nx run design-tokens:build && nx run design-tokens:lint/* libs/theme/src/styles/_primeng-bridge.scss */
@use 'libs/design-tokens/dist/tokens' as t;
:root.theme-light {
--ux-color-primary-500: #{t.$color.brand.primary.500};
--ux-color-surface-card: #{t.$color.surface.card};
--ux-text-high: #{t.$color.text.high};
--ux-radius-sm: #{t.$radius.sm};
--ux-spacing-200: #{t.$spacing[200]};
/* PrimeNG variables mapping */
--p-primary-color: var(--ux-color-primary-500);
--p-text-color: var(--ux-text-high);
--p-card-background: var(--ux-color-surface-card);
--p-border-radius: var(--ux-radius-sm);
}
:root.theme-dark { /* override a few for dark */ }
/* Density tokens */
:root.density-compact { --ux-density-scale: .9 }
:root.density-cozy { --ux-density-scale: 1 }
:root.density-comfortable { --ux-density-scale: 1.1 }
.p-button {
padding-inline: calc(var(--ux-spacing-200) * var(--ux-density-scale));
border-radius: var(--p-border-radius);
}// libs/theme/src/lib/theme.store.ts
import { Injectable, effect, signal } from '@angular/core';
export type ThemeName = 'theme-light' | 'theme-dark';
export type Density = 'density-compact' | 'density-cozy' | 'density-comfortable';
@Injectable({ providedIn: 'root' })
export class ThemeStore {
theme = signal<ThemeName>('theme-light');
density = signal<Density>('density-cozy');
scale = signal<number>(1);
constructor() {
effect(() => {
const root = document.documentElement.classList;
root.remove('theme-light', 'theme-dark');
root.add(this.theme());
root.remove('density-compact', 'density-cozy', 'density-comfortable');
root.add(this.density());
document.documentElement.style.setProperty('--ux-scale', String(this.scale()));
});
}
}<!-- Example PrimeNG button bound to tokens -->
<button pButton type="button" label="Save" class="p-button" aria-label="Save changes"></button>// .storybook/preview.ts
import type { Preview } from '@storybook/angular';
import { ThemeStore } from '../libs/theme/src/lib/theme.store';
export const globalTypes = {
theme: {
name: 'Theme',
description: 'Theme toggle',
defaultValue: 'theme-light',
toolbar: { items: ['theme-light', 'theme-dark'], showName: true }
},
density: {
name: 'Density',
description: 'Density scale',
defaultValue: 'density-cozy',
toolbar: { items: ['density-compact', 'density-cozy', 'density-comfortable'] }
}
};
const withTokens = (Story, ctx) => {
const store = new ThemeStore();
store.theme.set(ctx.globals['theme']);
store.density.set(ctx.globals['density']);
return Story();
};
const preview: Preview = {
decorators: [withTokens],
parameters: {
a11y: { element: '#root', manual: false },
chromatic: { diffThreshold: 0.03 }
}
};
export default preview;# .github/workflows/chromatic.yml
name: Chromatic
on:
pull_request:
push:
branches: [ main ]
jobs:
chromatic:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v3
with: { version: 9 }
- run: pnpm install --frozen-lockfile
- run: pnpm nx run design-tokens:build
- run: pnpm nx run storybook:build -- --output-dir dist/storybook
- uses: chromaui/action@v1
with:
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
buildScriptName: 'nx run storybook:build -- --output-dir dist/storybook'
exitZeroOnChanges: falseTokens source (Figma → repo)
Below is a minimal Tokens Studio export snippet.
Style Dictionary config
Transforms JSON into CSS vars, SCSS, and TS.
PrimeNG variable mapping + AngularUX palette
Map palette tokens to PrimeNG’s --p-* variables and our data-viz scales.
Signals for theme + density
A small store applies classes/vars and persists preferences.
Storybook + Chromatic setup
Global toolbar drives live token switching; CI runs Chromatic.
Accessibility, Typography, Density, and the AngularUX Palette
I’ve applied this palette on a telecom analytics dashboard where D3 maps, Highcharts time-series, and PrimeNG tables share one brand system. Data virtualization (cdk-virtual-scroll) keeps tables fluid while Signals drive state changes without re-render storms.
Meet AA by construction
Add @storybook/addon-a11y and block merges when contrast fails. Primary, danger, and success states must meet AA. I ship focus-visible tokens for keyboard users and announce async states via ARIA live regions.
Contrast tokens verified in Storybook
Live regions and focus styles
Typography tokens
The AngularUX typographic scale anchors at 16px (md) with tight (1.25) and normal (1.5) line heights. UI controls clamp font-size based on --ux-scale so kiosk and mobile don’t blow layout.
Modular scale
Motion-safe sizes
Density controls
PrimeNG paddings/margins compute from spacing tokens times density scale. Teams can toggle density without hunting for one-off CSS.
Compact/cozy/comfortable
Token-driven spacing
Data-viz alignment (D3/Highcharts/Three.js)
Pass token colors into D3 scales and Highcharts themes so charts and UI align. For heavy scenes (Canvas/Three.js), reference CSS vars once and cache to avoid layout thrash.
Color ramps from tokens
Canvas-friendly palette
Storybook Workflows that Ship: Visual Diffs, Firebase Previews, and Perf Budgets
# Optional Firebase preview for Storybook
name: Storybook Firebase Preview
on: pull_request
jobs:
preview:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v3
with: { version: 9 }
- run: pnpm install --frozen-lockfile
- run: pnpm nx run storybook:build -- --output-dir dist/storybook
- uses: FirebaseExtended/action-hosting-deploy@v0
with:
repoToken: '${{ secrets.GITHUB_TOKEN }}'
firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT }}'
channelId: pr-${{ github.event.number }}
projectId: your-firebase-project
target: storybookVisual diffs as merge gates
I set chromatic.diffThreshold to 0.02–0.05 depending on the component. We review empty/filled/error/disabled states. No more “it looked fine on my machine.”
Chromatic thresholds
Review isolated states
Firebase hosting for previews
Deploy Storybook to Firebase Hosting preview channels per PR. Designers get links they can annotate. Easy to demo tokens in isolation.
Temporary channels
QA-friendly links
Performance budgets
Run Lighthouse on Storybook iframes and fail the job if LCP > 2.5s or INP > 200ms. Use Angular DevTools flame charts to prove Signals reduced renders after theme/density toggles.
Bundle/INP/LCP checks
Flame charts
How an Angular Consultant Approaches Tokens Integration
If you need a remote Angular expert to wire this up quickly, I’m available for hire as an Angular contractor. Typical engagement: 2–4 weeks to stand up the pipeline and migrate core components.
Week 1: Assess + Prototype
I audit Figma tokens, export structure, and PrimeNG usage. We prototype Button, Input, and Card in Storybook with AA checks.
Audit tokens
Pick 3 components
Week 2–3: Bridge + Rollout
We add the SD pipeline, PrimeNG bridge, and a Theme/Density SignalStore. Chromatic gates land. Designers see Firebase previews.
Style Dictionary
SignalStore
Week 4+: Data-viz and edge cases
Charts and role-based palettes, then dark mode and locale-driven spacing/typography if needed. KPI: 0 visual regressions, AA pass rate ≥ 98%.
D3/Highcharts/Canvas
Locale/theming
When to Hire an Angular Developer for Legacy Rescue
For deeper modernization or vibe-coded app recovery, see how we stabilize your Angular codebase with gitPlumbers—visual guardrails included.
Symptoms you can measure
If theme flips cause layout shifts, if spacing is copy-pasted per component, or if your Lighthouse a11y scores fluctuate, it’s time to systematize tokens.
Janky theme toggles
Inconsistent spacing
AA failures
Rescue plan
I’ve rescued AngularJS/Angular 9–14 apps by introducing tokens incrementally, mapping to PrimeNG, and using Chromatic to prevent regressions—all without halting feature delivery.
Tokenize, don’t rewrite
Guard with CI
Example: Role-Based Dashboard Polish with Performance Budgets
Data virtualization handled 100k-row tables, and Highcharts pulled success/danger token ramps for alerts. The system stayed fast and consistent.
Scenario from the field
On an ads analytics platform, we themed executive vs. analyst dashboards with scoped tokens. Executives got larger typography and fewer controls; analysts got compact density and heatmapped tables.
Telecom analytics
Multi-role UI
Measurable outcomes
Chromatic blocked two spacing regressions and one contrast slip. After Signals + tokens, render counts dropped during theme swaps and Lighthouse a11y moved to 92+.
+92 Lighthouse a11y
0 visual regressions
Takeaways and Next Steps
- Export tokens once; consume everywhere (Angular, PrimeNG, Storybook, charts).
- Use Signals/SignalStore for theme and density switches without layout thrash.
- Guard UX with Chromatic diffs, a11y checks, and perf budgets in CI.
- Deploy previews to Firebase; let design review changes before merge.
- Measure outcomes with Lighthouse and Angular DevTools—then ship.
Key takeaways
- Treat design tokens as your design-to-code API; export once from Figma and consume in Angular, Storybook, and Chromatic.
- Use CSS variables to bridge tokens to PrimeNG and data-viz (D3/Highcharts). Signals toggle theme/density at runtime without re-render storms.
- Bake AA contrast, typography scale, and density controls into tokens. Measure with Lighthouse and Chromatic thresholds in CI.
- Run the loop: Tokens → Style Dictionary → CSS vars/TS types → PrimeNG theme overrides → Storybook → Chromatic/CI → Firebase preview.
- Guard rail everything: visual diffs, a11y checks, and performance budgets so UX polish doesn’t blow the performance budget.
Implementation checklist
- Export tokens from Figma (Tokens Studio) to JSON in your Nx monorepo.
- Transform tokens with Style Dictionary to CSS variables, SCSS maps, and TypeScript types.
- Map token variables to PrimeNG theme variables and AngularUX palette.
- Add a Theme/Density SignalStore and decorators in Storybook for live switching.
- Configure Chromatic for visual regression and set Lighthouse/perf budgets.
- Integrate D3/Highcharts color scales with tokens; verify AA contrast for states.
- Publish Storybook previews to Firebase and block merges on Chromatic diffs.
Questions we hear from teams
- How long does it take to connect Figma tokens to an Angular/PrimeNG app?
- A focused integration takes 2–4 weeks: Week 1 assess/prototype, Week 2–3 build the Style Dictionary + PrimeNG bridge and Signals store, Week 4 polish data‑viz and dark mode. Parallel feature work continues.
- What does an Angular consultant deliver for token integration?
- A working token pipeline, PrimeNG theme bridge, Storybook with theme/density controls, Chromatic visual regression gates, AA accessibility checks, and documentation your team can maintain in an Nx monorepo.
- How much does it cost to hire an Angular developer for this work?
- Pricing depends on scope and component inventory. Typical pilots start at two to three weeks; fixed-price packages available after a quick audit. Contact me to scope an engagement within 48 hours.
- Will this impact performance or bundle size?
- CSS variables keep runtime cheap. Signals apply theme/density with minimal change detection. We add Lighthouse budgets and Chromatic thresholds to catch regressions before merge.
- Can we apply tokens to D3/Highcharts and kiosk views?
- Yes. Token ramps feed D3/Highcharts themes, and density/scale tokens adapt kiosk/touch layouts. I’ve shipped this for telemetry dashboards and airport kiosk software with offline tolerance.
Ready to level up your Angular experience?
Let AngularUX review your Signals roadmap, design system, or SSR deployment plan.
NG Wave
Angular Component Library
A comprehensive collection of 110+ animated, interactive, and customizable Angular components. Converted from React Bits with full feature parity, built with Angular Signals, GSAP animations, and Three.js for stunning visual effects.
Explore Components