Introduction
Storybook is the industry standard for developing, documenting, and testing UI components in isolation. It gives you a sandbox where you can render every component variant, interact with it, and verify its behavior without running your full application.
For design systems, Storybook serves triple duty: it's a development environment, a documentation site, and a visual testing platform. With the right addons, it becomes the central hub for your component library.
This guide covers setting up Storybook with React, essential addons, writing effective stories, visual testing, and deploying Storybook as documentation.
Key Concepts
Installation and Configuration
# Initialize Storybook in your project
npx storybook@latest init
# .storybook/main.ts
import type { StorybookConfig } from '@storybook/react-vite';
const config: StorybookConfig = {
stories: ['../src/**/*.stories.@(ts|tsx)'],
addons: [
'@storybook/addon-essentials', // Controls, actions, viewport, docs
'@storybook/addon-a11y', // Accessibility checks
'@storybook/addon-interactions', // Interaction testing
],
framework: '@storybook/react-vite',
docs: { autodocs: 'tag' },
};
export default config;
Writing Stories
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';
const meta: Meta<typeof Button> = {
title: 'Components/Button',
component: Button,
tags: ['autodocs'], // Generate docs page
argTypes: {
variant: { control: 'select', options: ['primary', 'secondary', 'ghost', 'destructive'] },
size: { control: 'select', options: ['sm', 'md', 'lg'] },
},
};
export default meta;
type Story = StoryObj<typeof Button>;
export const Primary: Story = { args: { children: 'Primary Button', variant: 'primary' } };
export const Secondary: Story = { args: { children: 'Secondary', variant: 'secondary' } };
export const Loading: Story = { args: { children: 'Loading...', isLoading: true } };
export const AllVariants: Story = {
render: () => (
<div className="flex gap-4">
<Button variant="primary">Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="destructive">Destructive</Button>
</div>
),
};
Practical Examples
1. Interaction Testing
import { within, userEvent, expect } from '@storybook/test';
export const FormSubmission: Story = {
render: () => <ContactForm />,
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
await userEvent.type(canvas.getByLabelText('Name'), 'John Doe');
await userEvent.type(canvas.getByLabelText('Email'), 'john@example.com');
await userEvent.click(canvas.getByRole('button', { name: 'Submit' }));
await expect(canvas.getByText('Success!')).toBeInTheDocument();
},
};
2. Accessibility Addon
// The a11y addon automatically runs axe-core on every story
// Add it to .storybook/main.ts addons array
// '@storybook/addon-a11y'
// Override rules per story if needed
export const WithAccessibilityOverride: Story = {
parameters: {
a11y: {
config: {
rules: [{ id: 'color-contrast', enabled: false }],
},
},
},
};
3. Deploying Storybook to Chromatic
# Install Chromatic
npm install chromatic --save-dev
# Add to CI
# .github/workflows/storybook.yml
- name: Publish to Chromatic
uses: chromaui/action@latest
with:
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
buildScriptName: build-storybook
Best Practices
- ✅ Write stories for every component variant and state
- ✅ Use autodocs for automatic documentation generation
- ✅ Add the a11y addon and fix all violations
- ✅ Use interaction tests for complex component behavior
- ✅ Deploy Storybook as your component documentation site
- ❌ Don't write stories that only render the default state — cover edge cases
- ❌ Don't skip mobile viewport stories — test responsive behavior
Common Pitfalls
- Stories that don't match real usage — write stories that reflect how consumers actually use components
- Missing decorator for theme/context providers — components that need context will break
- Not testing dark mode — add a theme switcher toolbar addon
- Storybook build errors in CI — run storybook build locally before pushing
Related Guides
- Building Component Libraries — Components you're documenting in Storybook
- Design System Documentation — Storybook as documentation platform
- Accessibility Testing Tools — Using Storybook's a11y addon
- Design System Versioning — Visual regression testing for releases