AtomKit

AtomKit

Themeable React component library and design system, built to keep three internal products visually consistent without duplicating UI code.

ReactTypeScriptRadix UI primitivesTailwind CSSStorybookChangesets
View liveView repo

The problem

Three internal products at my last job each had their own button, input, and modal components, subtly different in padding, color, and focus behavior. Every design tweak had to be made three times and always drifted out of sync within a few weeks.

Role and impact

Technical decisions and challenges

Each product needed its own color palette and border radius scale, but I didn't want three forks of the same components. I compared shipping separate themed builds per product versus a single build driven entirely by CSS custom properties.

I chose CSS custom properties resolved at the theme-provider level, because it let every product consume the exact same compiled components and only override a small token file, instead of maintaining parallel builds that could drift.

Rewriting all three products' UI in one pass was too risky to ship safely. I evaluated a hard cutover per product versus a gradual, component-by-component migration behind the existing component API.

I went with a codemod that swapped one component at a time, keeping the old and new components' props API compatible during the transition, since it let each team migrate on their own schedule without a big-bang release that could break production.

Detailed stack

LayerTechnologyWhy
ComponentsReact, Radix UI primitivesAccessible behavior out of the box, unstyled so theming stays clean
StylingTailwind CSS, CSS custom propertiesPer-product theming without maintaining separate builds
DocsStorybookLiving documentation and visual regression baseline
ReleaseChangesetsIndependent, changelogged versioning per package
Storybook showing button variants across three product themesDesign tokens documentation page

What I would do differently

I would invest in automated visual regression testing from day one instead of adding it after the first cross-product migration. We caught a few theme-token regressions manually that a visual diff tool would have flagged immediately.