From Figma to Component Platform
You do not need to build a design system from scratch. Here is how to assemble one that scales — from design tokens to a shared component platform your teams actually want to use.
A shared component platform is one of the highest-leverage investments a product organisation can make. But the idea of building one often triggers the wrong reaction: a large, long-running platform project that tries to hand-craft every input, dropdown, and data table from scratch. There is a better way — start in Figma, pick a solid base library like PrimeNG for Angular, and let design tokens do the heavy lifting of keeping them in sync.
The Pipeline: Figma → Design Tokens → Components → Application
Most explanations of this pipeline describe Figma as the 'source of truth' and tokens as a convenient way to sync colours. That undersells what is actually happening.
The pipeline has four concrete stages, each distributed as its own artefact. Figma is where your UX designer works — components in Figma use variables (tokens) directly, so any change to a token updates the Figma component immediately. Those tokens are then exported and published as a standalone package. Each component is its own separate package that imports only the tokens it needs. Applications then declare dependencies on whichever component packages they need and compose their UI from them — Lego pieces assembled for a specific use case.
This works regardless of the UI technology your teams use. The token package and component packages are consumed the same way whether you are building in Angular, React, Blazor, or any other framework. The pipeline does not care.
The result is that a change made in Figma flows through the token package, into every component package that references that token, and out to every application — without touching a single line of component logic.
What Design Tokens Actually Are
Design tokens are CSS custom properties. Not abstractions over CSS — actual CSS variables that your components reference directly. A token like --button-padding-x or --card-border-radius is as concrete as any other CSS property. It has a value, and that value determines what gets rendered.
They work on two levels. Generic tokens express global design decisions: --color-primary, --spacing-4, --font-size-base. These are the building blocks. Specific tokens express component-level decisions: --button-bg uses --color-primary, --button-padding-x uses --spacing-4. The specific tokens reference the generic ones, so a change at the generic level cascades automatically to every component that depends on it.
This is what makes the Figma connection real. Figma's variables map directly to these tokens. When a designer sets a component's padding in Figma, that is not a design annotation to be interpreted by a developer — it is the token value. When they change it, the exported token changes, the CSS variable changes, and the component changes. The designer and the component are editing the same thing.
- Colour tokens: global palette, semantic roles (success, warning, error), surface and text hierarchy — referenced by every component that has a background or text colour
- Spacing tokens: a consistent scale that feeds padding, margin, gap, and positional values throughout every component
- Size tokens: widths, heights, icon sizes, border widths — so components stay proportionally consistent across the system
- Typography tokens: font family, size scale, line height, weight, letter spacing — used directly in component text styles
- Shape and depth tokens: border radii, shadow levels, z-index scale — controlling the spatial feel of the entire UI
- Motion tokens: duration and easing values consumed by any component that animates
You Do Not Have to Build Components From Scratch
This is the insight that changes the economics of a component platform entirely. Most organisations assume they need to hand-craft every component — every date picker, every multi-select, every data table. That is enormously expensive and produces components that are inevitably less accessible, less tested, and less robust than what established open-source libraries already ship.
A far more practical approach is to wrap a battle-tested third-party component library and expose it through your own API. If your teams use Angular, PrimeNG is an excellent foundation. React teams might wrap Radix UI or Headless UI. Blazor teams have their own ecosystem. The principle is the same: you adopt the interaction logic, accessibility handling, and edge-case coverage that the upstream library has already solved — and you own the design layer on top.
What this looks like in practice: you create a wrapper component (a web component or a framework-native component) that exposes only the props your teams need, hides implementation details, and delegates rendering to the upstream library. You apply your design tokens through the library's theming system. The result is a component that looks exactly like your UX design specifies and behaves exactly as the upstream library guarantees — with minimal custom logic of your own.
Theming, Not Overriding
Modern component libraries like PrimeNG are built to be driven by tokens. Their theming system exposes a structured set of CSS custom properties — one for every visual aspect of every component. You do not override their styles. You supply the token values and they render accordingly.
This is the integration point where Figma becomes the component. Your exported Figma tokens feed directly into the library's token layer. The library uses those values to render. When a designer changes a component's appearance in Figma, the token export updates, the library picks it up, and the rendered component reflects the change — automatically, with no component code touched.
The boundary is clean: the library owns interaction behaviour and accessibility, your tokens own every visual decision. That division is what keeps the platform maintainable as both the design and the library evolve.
Wrapping as a Web Component or Framework Component
Your wrapper strategy depends on how many frameworks your organisation runs. If all teams use the same framework — say Angular — a native Angular component wrapper is the simplest and most ergonomic choice. It participates naturally in Angular's change detection, dependency injection, and reactive forms.
If teams use different frameworks, wrapping as a web component (using Angular's @angular/elements, or a dedicated tool like Lit) lets you publish once and consume everywhere. The component works in Angular, React, Blazor, or plain HTML. The trade-off is slightly more complexity at the boundary — but for organisations with genuine polyglot frontends, it is the right trade.
Either way, the wrapper is thin. It owns the public API your teams use — the props, events, and slots — and delegates everything else to the upstream component. The less logic inside the wrapper, the easier it is to maintain.
Distributing as Packages
The token export from Figma is published as a dedicated package — a single distribution point for every CSS custom property in the system. It contains nothing else: no components, no utilities, just tokens.
Each component is then its own separate package. A button component imports only the tokens it needs — its background colour, padding scale, border radius, font size. A data table imports its own subset. Components are independent, versioned individually, and teams install only what their application actually uses.
An application that needs a search bar, a data table, and a date picker simply declares those three components as dependencies. It gets exactly those components, styled consistently through the shared token package. Building a new page becomes a matter of selecting the right components and composing them — pieces with well-defined shapes that fit together because they all share the same underlying token system.
Storybook sits alongside this as the interactive catalogue. Every component has stories showing its variants, states, and configuration. It is where developers discover what exists before they build, and where designers verify the token mapping is correct before a component is published.
What Maintenance Actually Looks Like
This is where the investment pays off. Because your components wrap an upstream library, most maintenance is inherited automatically. Bug fixes, accessibility improvements, and browser compatibility patches ship with the upstream library and flow into your platform on upgrade.
Your team's maintenance work concentrates on two things: keeping the token pipeline accurate as designs evolve, and managing the wrapper API as teams request new capabilities. Neither is trivial, but both are vastly smaller in scope than maintaining hand-crafted components from scratch.
When a rebrand happens — new primary colour, updated typography scale, adjusted border radius — the work is: update tokens in Figma, re-export, update theme configuration, publish a new version. Every consuming application picks up the change on their next dependency update. No component rewrite required.
The Platform Needs a Clear Owner
A component platform is infrastructure. Like any infrastructure, it needs someone accountable for it — not as a side project, but as a primary responsibility.
This means a small, dedicated team (or at minimum one focused engineer paired with the UX responsible) who owns the token pipeline, reviews component proposals, manages versioning, maintains Storybook, and communicates breaking changes to consuming teams.
Without clear ownership, the platform drifts. Tokens fall out of sync with Figma. Components accumulate undocumented variants. Teams start working around the platform rather than through it. The investment erodes.
The Payoff: Development as Assembly
When the platform is mature, the experience of building a new feature changes fundamentally. A product team receives a Figma design built with the existing token set and components. They open Storybook, find the components they need, and assemble the page. The visual output matches the design because both are driven by the same tokens.
AI-assisted development benefits directly from this: when your component library is available as context, a coding assistant can compose pages using your actual components rather than generating arbitrary markup. The first suggestion already uses the right components, the right props, and the right naming.
The result is faster delivery, fewer design inconsistencies, lower review overhead, and a product that feels cohesive — even when built by many teams working independently.
Related articles