One design system across React and Angular
A practical guide to sharing one design system across React and Angular, and any framework that reads CSS variables. The token-driven approach behind the bpdm/ui component libraries.
Most teams don't live in a single framework. An organisation ends up with a React product and an Angular admin, a legacy Angular app beside a newer React one, or two teams that each picked their own stack. The brand is meant to be one thing, yet the apps drift apart: a button with a different radius here, a focus ring in the wrong blue there, and every design change made twice by hand.
A shared design system is supposed to solve that. The hard part is sharing it across frameworks that can't run each other's code. Here's the approach that actually works, and it doesn't ask you to pick a winner.
Share the design, not the components
You can't drop a React component into an Angular app (or the reverse) without pain: different runtimes, bundle bloat, hydration quirks, accessibility that breaks in the seams. So don't try to share the components. Share the design instead.
A design token is a named value: a colour, a spacing step, a radius, an easing curve. Expressed as CSS custom properties, tokens are framework-agnostic. A <div> styled with var(--primary) looks identical no matter what rendered it.
:root {
--primary: #f5a623;
--radius: 0.5rem;
--ease: cubic-bezier(0.2, 0, 0, 1);
}The rule is simple: nothing about how a component looks lives inside the React or Angular code. Each component owns structure, behaviour, and accessibility; everything visual reads from the token layer. Ship that one file to every app and they all resolve to the same values. Change a token once and they all move together, because there is nothing to sync.
A native component library per framework
With the design sitting in tokens, each framework gets its own native implementation of the same components. Not a wrapper, not an iframe: real React components and real Angular components that happen to share a look.
That is what makes a genuine React and Angular component library possible from a single design system. The token layer guarantees the two match, while each side stays idiomatic to its own framework.
import { Button } from '@bpdm/ui/button';
export function Save() {
return <Button variant="primary">Save</Button>;
}import { BpdmButton } from '@bpdm/ng';
// template: <button bpdmButton variant="primary">Save</button>Accessibility, once per platform
Accessibility is the part teams most often duplicate and get subtly wrong. Keep it on each platform's own primitives, Radix on React and the Angular CDK on Angular, following the same WAI-ARIA patterns. You write it once per framework, with the tools built for that framework, and keyboard and screen-reader behaviour lines up across both.
It scales past React and Angular
The real payoff of putting design in tokens is that the token layer neither knows nor cares which framework consumes it. Anything that can read a CSS variable can join the system: a Vue app, a plain HTML page, a Web Component. React and Angular are simply the first two native implementations; the same --primary and --radius are ready for whatever target comes next, with no change to the design layer.
That is what makes the approach future-proof. You invest in one token system, and every framework you add later inherits the same look for free.
Try it with bpdm/ui
bpdm/ui is built exactly this way: one token package (@bpdm/tokens), a React library (@bpdm/ui), and an Angular library (@bpdm/ng), all sharing the same design. Four built-in themes, first-class TypeScript, accessible by default.
Install
Add bpdm/ui to a React or Angular project
Theming & tokens
Themes, dark mode, and overriding tokens
Takeaways
- Share the design (tokens), not the component code. Tokens are framework-agnostic.
- Give each framework a native component library; never wrap one inside another.
- Handle accessibility on each platform's own primitives, following the same WAI-ARIA patterns.
- Because the token layer is framework-agnostic, the same design system extends to any target that reads CSS variables, so it is ready for more frameworks without a rewrite.
If you run more than one framework and you're tired of keeping them in sync by hand, this is the pattern worth adopting, with or without bpdm/ui.