Built a multi-brand React design system that contrast-tests every brand in both themes
The WyattGo Design System is a React design system for data-dense products sold to several organizations at once. Six brands swap the accent at runtime, every color pairing is contrast-tested in light and dark, and a public gallery documents each component live.
Explore the live design system (opens in a new tab)
Outcomes
- Brand and theme combinations tested
- 6 brands × 2 themes
- Components
- 25
- Automated tests
- 134
- Raw values in component styles
- 0
Every promised text, border, focus, and fill pairing, computed from the token source on every test run.
Each with typed docs, live demos, and tests, plus the two regions that apply brand and theme.
Contracts, keyboard models, scheme parity, contrast, and stylesheet drift.
Enforced by lint, so all six brands and both themes work without a component knowing they exist.
The challenge
Operational software in healthcare is often one product sold to several organizations, each expecting its own brand, and used all day on dense dashboards that sit beside dark video surfaces. Theming is usually an afterthought: a brand color that reads well on a light page vanishes on a dark one, popovers open in the wrong theme, and accessibility is checked once, by hand, if at all. After building a design language like this inside a client's platform, I wanted one I own outright. The WyattGo Design System is a clean-room rebuild from a written specification, with none of the original code, values, or names.
Approach
- Wrote the specification first: layers, principles, token tiers, each component's contract, and the quality gates, so the build had one source of truth
- Defined tokens once in TypeScript, generating the stylesheet and driving a contrast matrix across six brands in light and dark. A brand that fails is rejected, not patched
- Made the theme regional instead of global, so a dark video stage can sit beside a light sidebar and every popover, dialog, and menu inherits the theme of whatever opened it
- Took keyboard, focus, and screen reader behavior from React Aria and added only the look, so every control is complete for keyboard and assistive technology users
- Typed the documentation against the package's exports, so a component shipped without docs or a live demo fails the build
What shipped
The gallery at design.wyattgo.com renders every component with live demos, a usage snippet, and do and don't lists. Global controls switch the brand, the theme (light, dark, or both side by side), the frame width, and reduced motion. They live in the URL, so any view is a shareable link.
Twenty-five components cover display, actions and inputs, surfaces, navigation, and feedback: status and count pills, a timeline grouped by day, a tab strip whose unavailable options stay focusable and explain why, single and multi select, dialogs and modals, a collapsible navigation rail, and a notification host with timed, sticky, and urgent toasts plus a tray that survives a reload.
A token explorer shows every semantic token as a swatch across brand and theme with its live contrast ratios, which makes the accessibility rules visible instead of only tested.
Stylelint rejects raw colors, radii, and durations in component styles, so no component can opt out of theming by accident. The same system now underpins the products WyattGo builds.
Stack
- React 19
- TypeScript
- React Aria Components
- CSS Modules
- Radix Colors
- Vite
- Vitest
- Testing Library
- Stylelint
Services involved
Have a problem shaped like this one?
Tell me what you're working with and you'll get an honest read on whether it's a fit.
Start a project