Component library2024MaintainerOngoing
Atlas UI
A token-driven React component library shared by six products, with visual regression tests and RTL support built in.
- React
- TypeScript
- Storybook
- Tailwind
6
products on the library
-45%
UI bugs reported per release
2 days
full rebrand rollout
The problem
Six products had six button components. Every rebrand meant weeks of find-and-replace and inconsistent accessibility.
Constraints
- Adopted incrementally, product by product
- WCAG 2.2 AA
- Bilingual and RTL by default
Architecture
Source
Design tokens
Figma variables
Library
Primitives
Components
Quality
Storybook
Visual diffs
Key decisions
Decision 01
Tokens compiled to CSS variables
Themes swap at runtime without rebuilding components, and products can override a token without forking.
Trade-off: Less type safety on raw values than a JS theme object.
Decision 02
Headless primitives underneath
Behaviour and accessibility live in unstyled primitives; the styled layer is thin and easy to replace per product.
Trade-off: Two layers to document.
In the code
packages/ui/src/Button.tsx
1export const Button = forwardRef<HTMLButtonElement, ButtonProps>(2 ({ variant = "primary", size = "md", loading, children, ...props }, ref) => (3 <button4 ref={ref}5 data-variant={variant}6 data-size={size}7 aria-busy={loading || undefined}8 className={cx("atlas-button", props.className)}9 {...props}10 >11 {loading ? <Spinner label="Loading" /> : children}12 </button>13 ),14);What I learned
- Adoption is a product problem: docs and migration codemods mattered more than components.