Now that we have design system primitives (Button, Input, Card), we need a way to document, preview, and test them in isolation. That’s where Storybook comes in.
Storybook provides:
- A component playground outside your app.
- Interactive docs for your design system.
- Addons for accessibility (a11y), viewport testing, and interaction testing.
1) Install Storybook
Run the official setup tool:
npx storybook@latest init
- Detects React + TypeScript + Vite automatically.
- Creates a
.storybook/folder with config. - Adds example stories in
src/stories/.
Start Storybook:
pnpm storybook
This launches on http://localhost:6006.
2) Configure TypeScript support
In .storybook/tsconfig.json, extend your root config:
{
"extends": "../tsconfig.json",
"include": ["../src", "./*.ts", "./*.tsx"]
}
3) Write your first story (Button)
Stories live alongside components or in src/stories/. Each story is a different state of a component.
// src/components/ui/Button.stories.tsx
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';
const meta: Meta<typeof Button> = {
title: 'UI/Button', // sidebar group
component: Button,
tags: ['autodocs'], // enables auto docs
argTypes: {
onClick: { action: 'clicked' },
},
};
export default meta;
// Story type
type Story = StoryObj<typeof Button>;
export const Primary: Story = {
args: {
children: 'Save',
variant: 'primary',
},
};
export const Secondary: Story = {
args: {
children: 'Cancel',
variant: 'secondary',
},
};
export const Danger: Story = {
args: {
children: 'Delete',
variant: 'danger',
},
};
Now you can toggle between Primary, Secondary, and Danger in Storybook.
4) Input story with error state
// src/components/ui/Input.stories.tsx
import type { Meta, StoryObj } from '@storybook/react';
import { Input } from './Input';
const meta: Meta<typeof Input> = {
title: 'UI/Input',
component: Input,
tags: ['autodocs'],
};
export default meta;
type Story = StoryObj<typeof Input>;
export const Default: Story = {
args: {
label: 'Email',
placeholder: 'you@example.com',
},
};
export const WithError: Story = {
args: {
label: 'Email',
placeholder: 'you@example.com',
error: 'Invalid email address',
},
};
5) Card story
// src/components/ui/Card.stories.tsx
import type { Meta, StoryObj } from '@storybook/react';
import { Card } from './Card';
const meta: Meta<typeof Card> = {
title: 'UI/Card',
component: Card,
tags: ['autodocs'],
};
export default meta;
type Story = StoryObj<typeof Card>;
export const Default: Story = {
args: {
children: <p>This is a card with content.</p>,
},
};
6) Useful addons
Install a few must-haves:
pnpm add -D @storybook/addon-a11y @storybook/addon-viewport @storybook/addon-interactions
Update .storybook/main.ts:
export default {
addons: [
'@storybook/addon-a11y',
'@storybook/addon-viewport',
'@storybook/addon-interactions'
],
};
- a11y → accessibility checks in panel.
- viewport → test responsive breakpoints.
- interactions → simulate clicks/keyboard.
7) Why Storybook matters
- Designers & devs share a living component library.
- Test edge cases without spinning up the whole app.
- Ensures your design system is documented.
✅ Wrap-Up
With Storybook:
- Every component has isolated stories.
- Docs update automatically when props/types change.
- Addons give a11y audits, responsive previews, and interaction testing.
Comments
Post a Comment