Quick Start: Storybook Up and Running in 5 Minutes
If you already have a React project, integrating Storybook takes just a few commands:
cd my-react-app
npx storybook@latest init
This command auto-detects React, installs dependencies, and generates a few sample stories. Once done, run:
npm run storybook
Open your browser at http://localhost:6006 — you’ll see the Storybook UI with sample components already rendered. No need to run the main app, no login required, no database setup needed.
Create your first story for the Button component. Create a Button.stories.jsx file right next to Button.jsx:
import Button from './Button';
export default {
title: 'Components/Button',
component: Button,
};
export const Primary = {
args: {
label: 'Click me',
variant: 'primary',
},
};
export const Disabled = {
args: {
label: 'Disabled',
disabled: true,
},
};
Save the file, switch back to your browser — the Button component appears instantly in the sidebar with 2 states: Primary and Disabled. You can click each state and edit props directly in the UI without touching the code.
What Problem Does Storybook Solve?
I once refactored a 50K-line codebase, and the biggest lesson I took away was that you need solid test coverage before you start — especially for UI components. During a refactor, you need to know immediately: did this Button break its layout?, what does this Card component look like with empty data? If you have to boot the entire app and navigate through 5 screens just to see one component — that’s pure wasted time.
Storybook solves exactly that: render components in isolation, independent of the app’s context. Each “story” is a specific state of a component. A component with 10 states → create 10 stories → everything is visible at a glance in Storybook.
Workflow Before and After Storybook
Before: Edit component → run app → navigate to the right page → check → spot the bug → fix → repeat. Each cycle takes 2–3 minutes.
After: Edit component → Storybook auto-reloads → see it instantly. Each cycle takes 5 seconds.
For larger teams, Storybook also serves as living documentation — designers can look at Storybook and see exactly what a component looks like without asking a developer. QA can test each state systematically without needing to set up complex data.
Going Deeper: Args, Controls, and Play Functions
Args and Controls — Edit Props Directly in the UI
The best part of Storybook is the Controls panel. When you define argTypes, Storybook automatically generates a UI for editing each prop:
export default {
title: 'Components/Card',
component: Card,
argTypes: {
variant: {
control: { type: 'select' },
options: ['default', 'outlined', 'elevated'],
},
loading: {
control: 'boolean',
},
title: {
control: 'text',
},
},
};
With this config, the Controls panel shows a dropdown for variant, a checkbox for loading, and a text input for title. Designers and product managers can try different combinations on their own without knowing any code.
Play Functions — Test Interactions Directly in Storybook
From Storybook 6.4 onwards, you can write interaction tests directly inside a story:
import { userEvent, within } from '@storybook/testing-library';
import { expect } from '@storybook/jest';
export const FormSubmit = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
await userEvent.type(canvas.getByLabelText('Email'), '[email protected]');
await userEvent.click(canvas.getByRole('button', { name: 'Submit' }));
await expect(
canvas.getByText('Submitted successfully!')
).toBeInTheDocument();
},
};
Storybook runs this play function automatically when you open the story. You can watch it live: the form gets filled in, the button gets clicked, the result appears — all running right inside Storybook without opening browser dev tools or writing a separate test file.
Advanced: Addons and CI/CD Integration
Essential Addons to Install Right Away
Storybook has a rich addon ecosystem. Here are a few I use regularly:
- @storybook/addon-a11y — automatically checks accessibility (WCAG) for each component
- @storybook/addon-viewport — preview components at different breakpoints (mobile, tablet, desktop)
- storybook-dark-mode — toggle dark/light mode to test theming
- @storybook/addon-docs — automatically generates documentation from JSDoc and PropTypes
Add addons to .storybook/main.js:
export default {
addons: [
'@storybook/addon-essentials',
'@storybook/addon-a11y',
'storybook-dark-mode',
],
};
Chromatic — Automated Visual Regression Testing
Chromatic (built by the Storybook team) integrates with GitHub Actions to capture snapshots of each story and compare them against a baseline. With every PR, Chromatic detects which components have changed visually and highlights them for reviewers.
npm install chromatic --save-dev
# .github/workflows/chromatic.yml
name: Chromatic
on: push
jobs:
chromatic:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- run: npm ci
- uses: chromaui/action@v1
with:
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
Combined with a CI/CD pipeline, you get a complete feedback loop: code push → Chromatic captures snapshots → reviewer approves visual changes → merge. No more “wait, why is this button broken and nobody noticed?”
Practical Tips for Using Storybook
Keep Stories Next to Their Components, Not in a Separate Folder
Place Button.stories.jsx in the same directory as Button.jsx, not inside a separate stories/ folder. When you delete a component, its story file gets deleted with it — you’ll never end up with “orphaned” stories pointing to components that no longer exist.
Write Stories for Edge Cases — Not Just the Happy Path
Most UI bugs happen at the edges: text that’s too long, images that fail to load, empty data, network errors. Write stories for those scenarios:
export const LongText = {
args: {
title: 'This is a very long title used to test whether the component overflows or gets truncated across different viewports',
},
};
export const EmptyState = {
args: { items: [] },
};
export const LoadingState = {
args: { loading: true },
};
Use Decorators to Mock Context Once and Reuse Everywhere
Many components require context like a Redux store, React Router, or a theme provider. Instead of repeating this setup in every file, declare global decorators in .storybook/preview.js:
import { ThemeProvider } from './theme';
import { Provider } from 'react-redux';
import { store } from '../src/store';
export const decorators = [
(Story) => (
<Provider store={store}>
<ThemeProvider>
<Story />
</ThemeProvider>
</Provider>
),
];
Set It Up Early — Don’t Wait for the Right Time
Storybook is easiest to set up when the codebase is still small. Once you have 100 components, backfilling stories becomes exhausting. I learned this the hard way — after finishing a 50K-line refactor, I then spent another 2 weeks just writing stories for everything that already existed.
Establish the convention from day one: every new component must have at least 2–3 stories before the PR merges. They don’t need to be perfect, but they need to exist. That’s the only way Storybook delivers lasting value over time.

