Atomic Design Tokens: Scaling Multi-Brand UI with Tailwind & Radix

Blessync Team

Blessync Team

9/7/2026

Atomic Design Tokens: Scaling Multi-Brand UI with Tailwind & Radix
# Atomic Design Tokens: Scaling Multi-Brand UI with Tailwind & Radix In the fast-paced world of SaaS, maintaining a consistent yet flexible design system across multiple brands and platforms is a formidable challenge. Our team faced this exact problem: we needed to serve both an enterprise SaaS product and a variety of marketing sites, each with its own unique visual identity, while keeping the underlying codebase efficient and maintainable. The solution? Atomic design tokens combined with the power of Tailwind CSS and Radix UI primitives. ## The Problem: One Codebase, Many Brands Traditionally, theming in CSS is done via global variables or CSS custom properties. However, as brands multiply, so do the variables, leading to a tangled mess of overrides and inconsistencies. We needed a systematic approach that would allow us to define design decisions at a granular level and compose them into cohesive brand themes. ## Atomic Design Tokens: The Foundation Design tokens are the visual atoms of a design system—they store values for colors, spacing, typography, and more. By making them **atomic**, we break them down to their most primitive level, such as `color.primary.500` or `space.md`. This granularity enables us to remix and match tokens to create distinct brand experiences without duplicating code. ### Token Architecture We structured our tokens in three layers: 1. **Primitive Tokens**: Raw values like hex codes, pixel sizes, and font weights. These are brand-agnostic. 2. **Semantic Tokens**: Abstract roles like `background`, `text`, `border`, which map to primitives. For example, `color.bg.default` might map to `color.neutral.100` in one brand and `color.brand.50` in another. 3. **Component Tokens**: Specific to components, e.g., `button.primary.bg`. These consume semantic tokens. This hierarchy allows us to define a base set of primitives and then create semantic mappings per brand. ## Tailwind CSS: Utility-First with Token Integration Tailwind CSS is renowned for its utility-first approach, but it also supports custom configuration via the `tailwind.config.js` file. We leverage this to bridge our tokens into Tailwind's utility classes. ### Extending Tailwind's Theme We map our semantic tokens to Tailwind's color, spacing, and typography scales. For instance: ```javascript // tailwind.config.js module.exports = { theme: { extend: { colors: { // Semantic tokens become color utilities background: { DEFAULT: 'var(--color-bg-default)', subtle: 'var(--color-bg-subtle)', }, text: { DEFAULT: 'var(--color-text-default)', muted: 'var(--color-text-muted)', }, }, spacing: { // Map spacing tokens to Tailwind's spacing scale '2xs': 'var(--space-2xs)', xs: 'var(--space-xs)', sm: 'var(--space-sm)', }, }, }, }; ``` By using CSS variables inside the config, we ensure that the utility classes reflect the active brand's values at runtime. ### Usage in Components Now, in our JSX, we can use Tailwind classes that are brand-aware: ```jsx ``` When the brand changes, the CSS variables update, and the button's appearance automatically adapts. ## Radix UI: Accessible, Unstyled Primitives Radix UI provides a set of accessible, unstyled primitives for building complex UI components. They are perfect for a design system because they handle behavior and accessibility, while we control the styling with our tokens. ### Integrating Radix with Tailwind We combine Radix's component structure with Tailwind classes that reference our tokens. For example, a dialog component might look like: ```jsx import * as Dialog from '@radix-ui/react-dialog'; const MyDialog = () => ( Edit profile Make changes to your profile here. ); ``` Because Radix components are unstyled, we have full control to apply our token-driven Tailwind utilities. ## Implementing Multi-Brand Support To support multiple brands, we define a CSS file per brand that sets the CSS variables based on our atomic tokens. For example: ```css /* brand-a.css */ :root { --color-bg-default: var(--color-neutral-100); --color-bg-subtle: var(--color-neutral-50); --color-text-default: var(--color-neutral-900); --color-text-muted: var(--color-neutral-500); --color-primary: var(--color-blue-500); --color-primary-foreground: white; } ``` ```css /* brand-b.css */ :root { --color-bg-default: var(--color-slate-100); --color-bg-subtle: var(--color-slate-50); --color-text-default: var(--color-slate-900); --color-text-muted: var(--color-slate-400); --color-primary: var(--color-orange-500); --color-primary-foreground: white; } ``` Then, we conditionally load the appropriate CSS file based on the brand context (e.g., subdomain, user role, or environment). This allows us to share the same React component library across all our products. ### Dynamic Brand Switching For a more dynamic approach, we can switch brands at runtime by changing the `data-theme` attribute on the root element and using CSS variables that are defined within a scope: ```css [data-theme='brand-a'] { --color-bg-default: var(--color-neutral-100); /* ... */ } [data-theme='brand-b'] { --color-bg-default: var(--color-slate-100); /* ... */ } ``` Then in JavaScript: ```javascript document.documentElement.setAttribute('data-theme', 'brand-b'); ``` This enables A/B testing or real-time theming without a full page reload. ## Benefits and Challenges ### Benefits - **Scalability**: New brands can be added by simply creating a new token mapping file. - **Consistency**: All components use the same semantic tokens, ensuring visual harmony across brands. - **Performance**: Tailwind's JIT compiler only generates used styles, and our CSS variables are lightweight. - **Accessibility**: Radix ensures our components are accessible out of the box. ### Challenges - **Token Maintenance**: Requires disciplined naming and documentation to avoid confusion. - **Tooling**: We built custom scripts to generate CSS variable files from our token JSON to keep them in sync. - **Learning Curve**: Teams need to understand the token hierarchy and when to use primitives vs. semantic tokens. ## Conclusion Atomic design tokens, when combined with Tailwind CSS and Radix UI, provide a robust foundation for building multi-brand SaaS interfaces. This architecture has allowed us to scale from a single product to a suite of enterprise tools and marketing sites, all sharing a single source of truth for design decisions. By investing in a token-driven approach, we've future-proofed our UI and streamlined our design-to-development handoff. If you're embarking on a similar journey, start small: identify your core semantic tokens, integrate them with Tailwind, and gradually migrate components to Radix. The payoff is a unified, flexible design system that can adapt to any brand you throw at it.