Storybook
Build and document React components in isolation
📚 What is Storybook?
Storybook is a development environment for building, testing, and documenting UI components in isolation. It helps you develop components independently from your app, making development faster and more organized with visual testing capabilities.
# Initialize Storybook in your project
npx storybook@latest init
# Start Storybook
npm run storybook
Key Storybook Features
Component Isolation
Develop components independently
export default {
component: Button
};
Stories
Document component variations
export const Primary = {
args: { label: 'Button' }
};
Controls
Interactive prop editing
argTypes: {
color: { control: 'color' }
}
Addons
Extend with powerful plugins
addons: [
'@storybook/addon-essentials'
]
🔹 Installing Storybook
Add Storybook to your existing React project with automatic configuration. The CLI detects your project setup and installs the appropriate dependencies and configuration files.
# Install Storybook in existing project
npx storybook@latest init
# Start Storybook development server
npm run storybook
# Build static Storybook
npm run build-storybook
Storybook will run at http://localhost:6006
🔹 Project Structure
Storybook adds a .storybook directory for configuration and creates story files alongside your components. This keeps documentation close to the code it describes.
my-app/
├── .storybook/
│ ├── main.js # Storybook configuration
│ └── preview.js # Global decorators & parameters
├── src/
│ ├── components/
│ │ ├── Button.jsx
│ │ └── Button.stories.jsx # Button stories
│ └── App.jsx
└── package.json
🔹 Creating Your First Story
Stories are written in CSF (Component Story Format) which exports component metadata and story variations. Each story represents a different state or use case of your component.
// src/components/Button.jsx
export default function Button({ label, onClick, variant = 'primary' }) {
return (
<button
onClick={onClick}
className={`btn btn-${variant}`}
>
{label}
</button>
);
}
// src/components/Button.stories.jsx
import Button from './Button';
export default {
title: 'Components/Button',
component: Button,
tags: ['autodocs']
};
export const Primary = {
args: {
label: 'Primary Button',
variant: 'primary'
}
};
export const Secondary = {
args: {
label: 'Secondary Button',
variant: 'secondary'
}
};
🔹 Story Args and Controls
Args define component props that can be edited interactively in Storybook. Controls automatically generate UI inputs for each arg, making it easy to test different prop combinations.
// Button.stories.jsx
export default {
title: 'Components/Button',
component: Button,
argTypes: {
label: { control: 'text' },
variant: {
control: 'select',
options: ['primary', 'secondary', 'danger']
},
disabled: { control: 'boolean' },
size: {
control: 'radio',
options: ['small', 'medium', 'large']
}
}
};
export const Interactive = {
args: {
label: 'Click me',
variant: 'primary',
disabled: false,
size: 'medium'
}
};
🔹 Multiple Stories
Create multiple stories to showcase different component states and variations. This helps document all possible use cases and makes testing edge cases easier.
// Card.stories.jsx
import Card from './Card';
export default {
title: 'Components/Card',
component: Card
};
export const Default = {
args: {
title: 'Card Title',
content: 'This is the card content.'
}
};
export const WithImage = {
args: {
title: 'Card with Image',
content: 'Card content here',
image: 'https://via.placeholder.com/300'
}
};
export const Loading = {
args: {
title: 'Loading...',
isLoading: true
}
};
export const Error = {
args: {
title: 'Error',
error: 'Something went wrong!'
}
};
🔹 Decorators
Decorators wrap stories with extra markup or context providers. Use them to add themes, routing, or state management to your component stories.
// Add decorator to single story
export const Centered = {
args: { label: 'Button' },
decorators: [
(Story) => (
<div style={{ display: 'flex', justifyContent: 'center' }}>
<Story />
</div>
)
]
};
// Add decorator to all stories in file
export default {
title: 'Components/Button',
component: Button,
decorators: [
(Story) => (
<div style={{ padding: '3rem' }}>
<Story />
</div>
)
]
};
🔹 Global Decorators
Apply decorators to all stories globally through the preview configuration. Perfect for adding theme providers, routers, or global styles to every story.
// .storybook/preview.js
import { ThemeProvider } from 'styled-components';
import { theme } from '../src/theme';
export const decorators = [
(Story) => (
<ThemeProvider theme={theme}>
<Story />
</ThemeProvider>
)
];
// With React Router
import { BrowserRouter } from 'react-router-dom';
export const decorators = [
(Story) => (
<BrowserRouter>
<Story />
</BrowserRouter>
)
];
🔹 Actions Addon
The Actions addon logs component events in the Storybook UI. It helps you verify that event handlers are called correctly with the right arguments.
import { action } from '@storybook/addon-actions';
export default {
title: 'Components/Button',
component: Button
};
export const WithActions = {
args: {
label: 'Click me',
onClick: action('button-clicked')
}
};
// Multiple actions
export const Form = {
args: {
onSubmit: action('form-submitted'),
onChange: action('input-changed'),
onFocus: action('input-focused')
}
};
🔹 Documentation
Storybook automatically generates documentation from your stories and component props. Add MDX files for custom documentation with interactive examples embedded inline.
// Button.stories.jsx
export default {
title: 'Components/Button',
component: Button,
tags: ['autodocs'], // Auto-generate docs
parameters: {
docs: {
description: {
component: 'A versatile button component with multiple variants.'
}
}
}
};
// Custom MDX documentation
// Button.mdx
import { Meta, Story, Canvas } from '@storybook/blocks';
import * as ButtonStories from './Button.stories';
<Meta of={ButtonStories} />
# Button Component
A reusable button component.
<Canvas of={ButtonStories.Primary} />
🔹 Essential Addons
Storybook addons extend functionality with tools for accessibility testing, responsive design, and more. The essentials addon bundle includes the most commonly used addons.
# Essentials addon (included by default)
# Includes: docs, controls, actions, viewport, backgrounds, toolbars
// .storybook/main.js
export default {
addons: [
'@storybook/addon-essentials',
'@storybook/addon-a11y', // Accessibility testing
'@storybook/addon-interactions' // Interaction testing
]
};
// Using viewport addon
export const Mobile = {
args: { label: 'Button' },
parameters: {
viewport: {
defaultViewport: 'mobile1'
}
}
};
🔹 Complete Example
A comprehensive example showing a component with multiple stories, controls, actions, and documentation. This demonstrates best practices for component documentation.
// src/components/Alert.jsx
export default function Alert({
type = 'info',
title,
message,
onClose
}) {
return (
<div className={`alert alert-${type}`}>
<h3>{title}</h3>
<p>{message}</p>
{onClose && (
<button onClick={onClose}>Close</button>
)}
</div>
);
}
// src/components/Alert.stories.jsx
import { action } from '@storybook/addon-actions';
import Alert from './Alert';
export default {
title: 'Components/Alert',
component: Alert,
tags: ['autodocs'],
argTypes: {
type: {
control: 'select',
options: ['info', 'success', 'warning', 'error']
}
}
};
export const Info = {
args: {
type: 'info',
title: 'Information',
message: 'This is an informational message.',
onClose: action('close-clicked')
}
};
export const Success = {
args: {
type: 'success',
title: 'Success!',
message: 'Operation completed successfully.'
}
};
export const Error = {
args: {
type: 'error',
title: 'Error',
message: 'Something went wrong.'
}
};