Skip to main content

Tutorial: Build a Production Design System Kernel

Why this tutorial matters

A design system is not a component gallery. It is a product infrastructure layer: tokens, primitives, accessibility contracts, API design, theming, documentation, testing, release governance, and migration support. This tutorial builds a mid-level Design System Kernel that can support product teams and GenUI component registries.

The word "kernel" is intentional. You are not building every component. You are building the smallest stable foundation that future components can trust.

What you will build

AssetPurpose
Design tokensShared color, spacing, typography, radius, motion, z-index
Primitive componentsButton, TextField, Dialog, Tabs, Toast, DataTable shell
Accessibility contractsKeyboard, focus, labels, ARIA, live regions
Storybook docsIsolated states, usage examples, anti-patterns
Test harnessUnit, interaction, accessibility, visual checks
Release processVersioning, changelog, migration notes
GenUI registry bridgeApproved components and prop schemas for AI-generated UI

Milestone 1: Token architecture

Create layered tokens:

base tokens       color.blue.600, space.4, font.size.3
semantic tokens color.action.primary, color.surface.danger
component tokens button.primary.bg, dialog.backdrop.bg

Rules:

  • product code uses semantic/component tokens, not raw palette tokens
  • dark/high-contrast themes override semantic tokens
  • tokens are exported to CSS variables and TypeScript types
  • token changes have visual regression coverage

Acceptance criteria:

  • Button and Dialog can switch theme without changing component code.
  • No hard-coded product colors remain in kernel examples.
  • Token documentation explains intended usage, not only values.

Milestone 2: Build accessible primitives

Start with six primitives:

ComponentRequired states
Buttondefault, hover, focus-visible, loading, disabled, destructive
TextFieldlabel, hint, error, required, disabled, async validation
Dialogopen, close, focus trap, restore focus, escape, backdrop
Tabskeyboard navigation, selected state, disabled tab
Toaststatus, error, action, live region behavior
DataTable shellcaption, headers, empty, loading, row action

For each component, document:

  • anatomy
  • props
  • accessibility behavior
  • keyboard behavior
  • error states
  • composition limits
  • examples and anti-patterns

Acceptance criteria:

  • Every form input has label and error association.
  • Dialog focus is trapped and restored.
  • Tabs work with keyboard.
  • Toasts use appropriate live region behavior.

Milestone 3: Component API design

Design APIs for durable use.

Bad:

<Button blue big rounded shadow submitThing />

Better:

<Button variant="primary" size="md" type="submit" isLoading={saving}>
Save changes
</Button>

API rules:

  • use semantic variants, not visual adjectives
  • avoid boolean prop explosions
  • allow composition where product needs vary
  • keep destructive and loading states explicit
  • use controlled/uncontrolled patterns intentionally
  • reserve escape hatches for reviewed cases

Acceptance criteria:

  • Button and TextField APIs support common product use without style overrides.
  • Invalid combinations are prevented by types or runtime warnings.
  • Component docs explain when not to use the component.

Milestone 4: Storybook as verification surface

Storybook should become a workshop and contract surface.

Required story categories:

  • default
  • all variants
  • long text
  • narrow viewport
  • keyboard/focus
  • loading
  • empty
  • error
  • disabled
  • RTL or localization stress where relevant

Quality gates:

  • story exists for every public component
  • accessibility addon/manual checks run on stories
  • visual snapshots cover stable states
  • docs include usage and anti-patterns

Acceptance criteria:

  • A reviewer can inspect every critical state without running the app.
  • Component examples are not marketing demos; they include failure states.

Milestone 5: Theming and white-label constraints

Add two themes:

  • default
  • high-contrast or partner theme

Theming contract:

ConcernRule
colorsemantic tokens only
spacingcomponent density tokens
typographyrole-based text styles
logos/imagesapp-level, not primitive-level
motionrespects reduced motion
contrastverified for text and controls

Acceptance criteria:

  • Components pass contrast checks in both themes.
  • Theme change does not alter layout unexpectedly.
  • Partner theme cannot override component behavior.

Milestone 6: GenUI registry bridge

Create a registry file that exposes only safe components to GenUI:

export const genUIRegistry = {
summary_panel: {
version: "1",
component: SummaryPanel,
propsSchema: SummaryPanelSchema,
risk: "display",
},
approval_action: {
version: "1",
component: ApprovalAction,
propsSchema: ApprovalActionSchema,
risk: "approval",
},
};

Rules:

  • not every design-system component is GenUI-safe
  • GenUI props are stricter than React props
  • generated content must have fallback and validation
  • AI-accessible components include accessibility requirements

Acceptance criteria:

  • Unknown GenUI components are rejected.
  • Invalid GenUI props render fallback.
  • Approval components require explicit action and audit metadata.

Milestone 7: Release governance

Use semver-like rules:

ChangeVersion impact
new optional propminor
visual fix within contractpatch
removed propmajor
changed keyboard behaviormajor or explicit migration
token semantic changemigration note required

Release checklist:

  • changelog
  • migration notes
  • visual regression
  • accessibility checks
  • consuming app smoke test
  • design review signoff for behavior changes

Package structure

Use a package layout that separates primitives, tokens, docs, and test utilities:

packages/design-system/
src/
tokens/
primitives/
recipes/
theme/
genui/
testing/
stories/
docs/
FolderRule
tokensno React imports
primitivesgeneric accessible components
recipescomposed patterns such as form rows or empty states
themeCSS variables and theme providers
genuistrict schemas and safe registry exports
testinghelpers for consumers

Component readiness checklist

Before a component is public:

  • props are typed and documented
  • keyboard behavior is documented
  • focus behavior is tested
  • error/loading/empty states exist
  • long text and localization stress stories exist
  • accessibility tests run
  • visual snapshots exist
  • mobile/narrow layout story exists
  • usage examples include do/don't guidance

If a component lacks failure states, it is not production-ready.

Product adoption plan

Adopt through one vertical slice:

  1. Replace buttons and text fields in one form.
  2. Replace dialog behavior in one high-risk workflow.
  3. Add table shell to one data-heavy surface.
  4. Move one route to semantic tokens.
  5. Add Storybook links to product PRs.

Track:

  • component adoption
  • style override count
  • accessibility defects by component
  • duplicate component implementations
  • design-token violations

GenUI-specific hardening

For GenUI-safe components:

RequirementReason
strict prop schemamodel output is untrusted
max text lengthprevents layout breakage
required labelsprotects accessibility
allowed event namesprevents arbitrary actions
citation support where neededsupports trust
fallback renderinghandles invalid generated UI

Do not expose raw Dialog, Table, or Form composition to GenUI until you have safe wrappers. AI should target recipes, not low-level primitives.

Capstone review

Answer:

  • Which components are primitives vs product-specific?
  • Which tokens can product teams use?
  • Which accessibility behaviors are guaranteed?
  • Which escape hatches exist and who approves them?
  • Which components are safe for GenUI?
  • How are breaking changes communicated?

Source lens

This tutorial is informed by Storybook's component isolation/documentation model, WCAG 2.2 principles, and the book's chapters on design systems, tokens, durable component APIs, accessibility contracts, theming, and inclusive component recipes.