Storybook went from a nice-to-have demo tool to a core part of the component development workflow between 2023 and 2026. Version 8 switched to Vite as the default builder, added a built-in test runner powered by Playwright, and tightened the TypeScript story format. If you write UI components, this is the setup that pays for itself in the first PR review cycle.
What changed in 2026
- Storybook 8 ships with the Vite builder by default — no Webpack unless you opt in. Cold starts went from 20–30 s to under 3 s on a typical project.
@storybook/test unified @storybook/jest and @storybook/testing-library into one package matching Vitest/Playwright conventions.
Component Story Format 3 (CSF3) is the only format you need — object-style, TypeScript-native, no more default export decorators mess.
- Autodocs generates a full API table from your TypeScript props automatically — no manual MDX doc page required.
storybook dev --test runs stories + interaction tests in headless mode for CI with one command.
Install
npx storybook@latest init
# Detects your framework (React, Vue, Svelte, etc.) and configures automatically
For an existing Vite project it will add .storybook/main.ts, .storybook/preview.ts, and example stories.
Configure .storybook/main.ts
import type { StorybookConfig } from '@storybook/react-vite'
const config: StorybookConfig = {
stories: ['../src/**/*.stories.@(ts|tsx)'],
addons: [
'@storybook/addon-essentials',
'@storybook/addon-a11y',
'@storybook/addon-interactions',
],
framework: { name: '@storybook/react-vite', options: {} },
docs: { autodocs: 'tag' },
}
export default config
Write a story
// src/components/Button/Button.stories.tsx
import type { Meta, StoryObj } from '@storybook/react'
import { Button } from './Button'
const meta: Meta<typeof Button> = {
component: Button,
tags: ['autodocs'],
argTypes: {
variant: { control: 'select', options: ['primary', 'secondary', 'ghost'] },
},
}
export default meta
type Story = StoryObj<typeof Button>
export const Primary: Story = {
args: { variant: 'primary', children: 'Save changes' },
}
export const Loading: Story = {
args: { variant: 'primary', loading: true, children: 'Saving…' },
}
Add interaction tests
// src/components/LoginForm/LoginForm.stories.tsx
import { within, userEvent, expect } from '@storybook/test'
export const FilledAndSubmitted: Story = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement)
await userEvent.type(canvas.getByLabelText(/email/i), 'user@example.com')
await userEvent.type(canvas.getByLabelText(/password/i), 'secret')
await userEvent.click(canvas.getByRole('button', { name: /sign in/i }))
await expect(canvas.getByText(/welcome/i)).toBeInTheDocument()
},
}
Run interaction tests in CI:
npx storybook dev --ci --test
# or
npx storybook build && npx storybook test --url http://localhost:6006
Story patterns table
| Pattern |
When to use |
| Default / empty state |
Every component |
| Loading / skeleton state |
Async components |
| Error / invalid state |
Forms, data fetchers |
| All variants in one story |
Design reference |
| Interaction (play fn) |
Interactive components |
| A11y violation check |
Public-facing UI |
Storybook vs alternative approaches
| Approach |
Good for |
Weakness |
| Storybook 8 |
UI components, design review |
Adds dev dependency |
| Vitest + RTL |
Logic-heavy components |
No visual preview |
| Playwright component |
Real browser tests |
Slower feedback loop |
| Manual dev page |
One-off debugging |
Doesn't scale |
How to pick what to story
- Every shared component in a design system — stories become the living spec.
- Components with multiple variants — props tables from autodocs replace Figma spec sheets.
- Components with complex interaction — write a
play function instead of a separate e2e test.
- Skip: leaf utilities, hooks, and helper functions — test those in Vitest, not Storybook.
Common mistakes
Storing mocked data only in stories — if your mock data is useful elsewhere, put it in a shared __fixtures__ file and import into the story.
Forgetting to tag autodocs — without tags: ['autodocs'] in the meta, the auto-generated docs page isn't built.
Using the Webpack builder — unless you have a legacy project with Webpack-only plugins, there's no reason not to use the Vite builder in 2026.
Not running stories in CI — Storybook's value drops if nobody catches broken stories before merge. Add storybook test to your pipeline.
What to skip
- MDX docs pages for every component — autodocs does 80% of the job; write MDX only for complex usage guides.
storybook-addon-designs Figma embeds — useful for design handoff but adds overhead; evaluate whether your team actually reads them.
- Multiple frameworks in one Storybook — it's possible but painful; keep one Storybook per framework package.
FAQ
Can I use Storybook without React?
Yes. Storybook 8 supports Vue 3, Svelte 5, Angular 17+, Web Components, and more. The setup command auto-detects the framework.
Does Storybook replace e2e tests?
No — interaction tests in Storybook run in a browser-like iframe context, not a real user session. Use them for component-level flows; use Playwright for full user journeys.
How do I handle global providers (theme, auth)?
Wrap in .storybook/preview.ts via decorators. Any provider you add there applies to every story.
How expensive is Chromatic?
Chromatic's free tier covers ~5,000 snapshots/month, which is enough for a small project. Paid plans start at ~$149/month for larger teams.
Where to go next