One architecture. Infinite design systems.
Patterns compose atoms, atoms reference tokens, themes override tokens. One source, infinite skins.
Toucan is a design system that builds design systems. Swap a single JSON file and every component, every pattern, every layout re-skins itself — no code changes, no overrides, no hacks.
Explore the systemDesign systems have a coupling problem
Existing approaches tangle concerns, we ensure purposeful independence.
Your components shouldn't dictate your aesthetics
Component libraries ship with baked-in styling opinions. Want a different look? You're fighting the framework — overriding CSS, wrapping components, or forking the source. The visual layer and the structural layer are glued together.
Unstyled primitives are only half the answer
Headless libraries give you accessible structure but leave you to build the entire visual system from scratch. Every team reinvents token architecture, theme switching, and style composition. The hard part isn't the components — it's the system around them.
Copying components doesn't scale
Copy-paste approaches feel fast until you need a second theme, a design refresh, or cross-product consistency. Without a token cascade, every component is an island. Change the brand colour and you're updating fifty files.
Three threads, zero entanglement
Toucan separates every design system into three independent concerns. Change one without touching the others.
Tokens
A complete token system ships out of the box — raw values, semantic aliases, and system-level component tokens, three tiers that cascade automatically. To theme it, you only override at the system level. The Wiz'rd GUI makes that even easier: pick colours, adjust spacing, and export a ready-made theme file.
Components
37 accessible React primitives emit semantic HTML, ARIA attributes, and data-* state hooks. They contain zero CSS, zero visual logic, zero animation. A Button renders a <button> with the right accessibility contract — what it looks like is entirely the token layer's job.
Interaction
Transitions, easing curves, type-ahead, drag gestures — all deferred to a dedicated motion layer. V1 components change state instantly. When the interaction thread ships, it plugs in without touching structure or aesthetics. This is what strict separation buys you.
The cascade that makes it all work
Three tiers of tokens. Each tier references the one below it. Themes override at any level.
// Raw: the actual value
"color": { "neutral": { "900": { "value": "#171717" } } }
// Alias: semantic meaning
"color": { "primary": { "value": "{color.neutral.900}" } }
// System: component binding
"button": { "surface": { "default": { "value": "{color.primary}" } } }// Custom theme: remap primary to blue
"color": { "primary": { "value": "{color.blue.600}" } }
// Every component that references color.primary
// re-skins automatically. Zero component code changes./* Base (no theme attribute) */
:root {
--color-primary: var(--color-neutral-900);
--button-surface-default: var(--color-primary);
}
/* Custom theme */
[data-theme="ocean"] {
--color-primary: var(--color-blue-600);
/* --button-surface-default already references --color-primary */
/* It updates automatically. That's the cascade. */
}Most theming happens at the system level — partial JSON files that remap token references, with the CSS cascade doing the rest. When you need finer control, component-level overrides are there too — like giving input fields a white surface instead of inheriting surface-default. A theme that overrides nothing is identical to base.
37 primitives, built from scratch
Every component is accessible by default. No Radix, no Headless UI — hand-crafted ARIA, keyboard navigation, and focus management.
Flex
Single-axis flex layout. Column by default (mobile-first), with optional row direction at a breakpoint, wrap, alignment, and justification.
FlexItem
Child of Flex that controls grow and shrink behavior.
Grid
Responsive grid layout with fixed or auto-fit columns, gap control, and container queries.
GridItem
Child of Grid that can span multiple columns.
Page
Full-viewport wrapper with themed background and text colour. The outermost layout container for an application.
Section
Full-width page band with optional background, vertical padding, and gap. Compose with Wrapper for centered content.
Wrapper
Centered max-width container with horizontal padding. Controls content width and provides edge breathing room on small viewports.
Button
Triggers actions. Supports primary, secondary, ghost, and danger variants with three sizes.
Checkbox
Checkbox with label, description, error state, and indeterminate support.
Input
Text input with built-in label, description, error state, and ARIA wiring.
RadioGroup
Radio button group with managed selection, label, and keyboard navigation.
Select
Custom select dropdown with keyboard navigation, label, and error support.
Textarea
Multi-line text input with label, description, error state, and resize control.
Toggle
On/off switch with label, description, and two sizes.
Slider
Range slider with keyboard, pointer drag, and full ARIA support. Horizontal or vertical orientation.
Avatar
User or entity avatar with image, initials fallback, and size variants.
Badge
Inline label for status, category, or count. Five variants, three sizes.
Box
Presentational container with elevation, radius, and padding. For backgrounds, borders, and visual grouping.
Rating
Read-only star rating display. Renders filled, half-filled, and empty stars with token-driven colors and three sizes.
Heading
Heading levels 1–6 with optional display sizes for visual hierarchy.
Separator
Horizontal or vertical line to divide content sections.
Table
Compound table component with caption, sortable headers, striped rows, and dense mode.
Text
Body text primitive. Renders paragraphs, spans, labels, and other inline text.
Alert
Thin accessibility wrapper with role="alert", variant colours, and custom colour support. Layout is composed freely via children.
Progress
Determinate or indeterminate progress bar with label and three sizes.
Skeleton
Loading placeholder in text, heading, circular, or rectangular shapes.
Toast
Notification toast system with stacking, auto-dismiss, pause on hover, and variant-based roles.
Dialog
Modal dialog with backdrop, focus trapping, and escape-to-close.
DropdownMenu
Action menu with items, labels, separators, and keyboard navigation. Compound component.
Popover
Floating content panel triggered by a button. Compound component with Trigger and Content.
Tooltip
Floating label that appears on hover or focus. Multiple anchor options.
Drawer
Slide-out panel from any edge. Focus trap, scroll lock, and backdrop. Uses the dialog machine internally.
36 patterns. Theme-agnostic by design.
Patterns compose atoms. Their CSS uses token references, so they re-skin automatically under any theme.
MetricCard
Dashboard KPI card with label, value, change indicator, and trend direction.
FeatureCard
Feature highlight card with icon, title, and description text.
PricingCard
Pricing tier card with price, features list, CTA, and highlighted variant.
TestimonialCard
Quote card with attribution, avatar, and role.
ProfileCard
Person card with avatar, bio, and action buttons.
ContactCard
Person or record card with avatar, status badge, and contact info.
AuthCard
Authentication form card with dynamic fields, submit button, and footer slot.
DataTableFull
Full data table with sortable columns, badge cell values, and optional caption.
DataTableRow
Single data row with label, value, optional secondary text and status badge.
FieldRow
Label-value pair for displaying key-value information.
StatsRow
Horizontal row of statistics with labels, values, and trend indicators.
ComparisonTable
Feature comparison matrix across multiple products with badge support.
AlertBanner
Full-width notification banner with message, variant, and optional action.
NotificationItem
Notification entry with user avatar, message, timestamp, and unread state.
CommentThread
Comment with user avatar, body text, timestamp, and reply action.
ActivityItem
Timeline or feed entry with user avatar, action text, and timestamp.
TimelineGroup
Groups timeline entries under a date heading.
SectionHeader
Section title with optional eyebrow badge, subtitle, and alignment control.
CodeBlock
Code display with optional filename header and copy button.
SettingsRow
Settings option with label, description, and control slot.
Footer
Site footer with column links, logo, and legal text.
Carousel
CSS scroll-snap carousel with navigation arrows, dots, and IntersectionObserver-based slide tracking.
FormField
Wraps a form atom with validation rules, managing dirty/touched/error state and injecting the resolved error string via cloneElement.
Form
Wraps FormField children in a <form> with Grid layout, gating submit behind validation of all registered fields.
FormSection
Groups related form fields under a heading with optional description.
How Toucan compares
Honest positioning. Every tool has strengths — here's where Toucan fits.
| Feature | Toucan | MUI | Chakra | Radix | Headless UI | shadcn/ui |
|---|---|---|---|---|---|---|
| Accessible components | Hand-crafted | Yes | Yes | Yes | Yes | Via Radix |
| Token architecture | 3-tier cascade | Theme object | Theme object | None | None | CSS variables |
| Theme switching | data-theme attr | ThemeProvider | ChakraProvider | N/A | N/A | CSS variables |
| Multi-theme from one source | Core design | Possible (work) | Possible (work) | N/A | N/A | Manual |
| Structure/style separation | Strict | No | No | Yes | Yes | Partial |
| CSS strategy | Custom properties | Emotion/CSS-in-JS | Emotion/CSS-in-JS | None (BYO) | None (BYO) | Tailwind |
| Framework-agnostic tokens | Yes (CSS vars) | No (JS) | No (JS) | N/A | N/A | No (Tailwind) |
| Component count | 37 | 50+ | 100+ | 30+ | 16 | 55+ |
| Bundle includes CSS runtime | No | Yes | Yes | No | No | No |
| Animation system | V2 | Built-in | Built-in | None | Minimal | Via Tailwind |
| Production maturity | Portfolio | Enterprise | Production | Production | Production | Production |
Accessibility isn't a feature. It's the foundation.
Every component is built accessibility-first, not accessibility-patched.
Toucan's 37 components are built from scratch — no wrapper libraries, no accessibility plugins, no "add ARIA later". Every component starts from the WAI-ARIA Authoring Practices and implements keyboard navigation, focus management, screen reader announcements, and semantic HTML as the first code written, not the last.
Keyboard navigation
Full keyboard support across all interactive components. Tabs arrow between panels, dropdown menus support Up/Down/Home/End, dialogs trap focus, and Escape closes overlays. Tested against WAI-ARIA Authoring Practices.
Screen reader semantics
Semantic HTML first, ARIA attributes where HTML falls short. Every component exposes the right roles, states, and properties. LiveRegions announce dynamic changes. Labels are required, not optional.
Focus management
Custom useFocusTrap for modals and overlays. Focus returns to trigger elements on close. No focus-trapping libraries — built to understand exactly what's happening.
Automated testing
Every component runs axe-core in its test suite. 1,035 tests total, with accessibility assertions throughout. Not a checkbox — a continuous guarantee.
Two imports. That's it.
Base tokens and the components you need.
// 1. Load the design system's CSS foundation
import '@toucan-ui/tokens/css';
// 2. Use components
import { Button, Heading, Box } from '@toucan-ui/core';
function App() {
return (
<Box elevation={2} padding="lg">
<Heading level={2}>Dashboard</Heading>
<Button variant="primary">Get started</Button>
</Box>
);
}@toucan-ui/tokens/css loads 762 design tokens as CSS custom properties plus the atom CSS that maps them to component classes. Components from @toucan-ui/core emit semantic HTML with the right classes and data-* attributes. The atom CSS does the rest.
No runtime. No CSS-in-JS. No build plugin. Just CSS custom properties and clean HTML.
What V1 doesn't do (and why)
Shipping incomplete is a feature when the boundaries are intentional.
No animation or transitions. V1 components change state instantly. No hover transitions, no enter/exit animations, no easing curves. This is intentional — the interaction thread is a V2 concern, and mixing it into V1 would compromise the strict three-thread separation that makes the architecture work.
No SSR optimization. Components work in SSR environments but haven't been optimized for streaming, selective hydration, or React Server Components. The docs site (Next.js 16) will stress-test this.
37 components, not 50+. Toucan ships the primitives that most design systems need. It doesn't include charts, date pickers, rich text editors, or virtualized lists. The architecture supports adding them — but V1 prioritizes depth over breadth.
React only (for now). Components are React 19. The token layer is framework-agnostic (CSS custom properties), and the component API contracts are documented independently of React for future Native Web Components and Flutter portability. But today, it's React.
V2 Roadmap
Pluggable motion system — transitions, transforms, easing, enter/exit animations.
Out of the box themed verticals for use or inspiration, think marketing, e-commerce and editorial UI's.
Native Web Components and Flutter component packages using the same token layer.
Multi-step forms, data grids, command palettes.
Figma token plugin that reads the same JSON source.