Wire Figma Tokens into PrimeNG + Angular 20 with Storybook and Chromatic: Accessible Typography, Density, and Real CI Guardrails

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: false

Tokens 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: storybook

Visual 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.

Related Resources

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.

Hire Matthew – Remote Angular Expert, Available Now See how we rescue chaotic code with visual guardrails

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
NG Wave Component Library

Related resources