Storybook for Next.js: Component Development in Isolation
Building UI components inside your full app means wrestling with auth, routing, and data just to see a button. Storybook lets you develop and test components in complete isolation.
Install
npx storybook@latest init
# Detects Next.js, installs @storybook/nextjs automatically
Your First Story
// components/Button/Button.stories.tsx
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';
const meta: Meta<typeof Button> = {
title: 'UI/Button',
component: Button,
parameters: { layout: 'centered' },
argTypes: {
variant: { control: 'select', options: ['primary', 'secondary', 'destructive'] },
size: { control: 'radio', options: ['sm', 'md', 'lg'] },
disabled: { control: 'boolean' },
},
};
export default meta;
type Story = StoryObj<typeof Button>;
export const Primary: Story = {
args: { variant: 'primary', children: 'Click me' },
};
export const Destructive: Story = {
args: { variant: 'destructive', children: 'Delete' },
};
export const Loading: Story = {
args: { loading: true, children: 'Save' },
};
Stories for Complex Components
// components/DataTable/DataTable.stories.tsx
export const WithData: Story = {
args: {
columns: [
{ key: 'name', header: 'Name' },
{ key: 'email', header: 'Email' },
{ key: 'plan', header: 'Plan' },
],
data: [
{ name: 'Atlas', email: 'atlas@whoffagents.com', plan: 'pro' },
{ name: 'Will', email: 'will@example.com', plan: 'free' },
],
},
};
export const Empty: Story = {
args: { data: [], emptyMessage: 'No users found' },
};
export const Loading: Story = {
args: { loading: true },
};
Decorators (Context Providers)
// .storybook/preview.tsx
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
const queryClient = new QueryClient();
export const decorators = [
(Story) => (
<QueryClientProvider client={queryClient}>
<Story />
</QueryClientProvider>
),
];
Interaction Testing
import { within, userEvent, expect } from '@storybook/test';
export const SubmitForm: Story = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
await userEvent.type(canvas.getByLabelText('Email'), 'user@test.com');
await userEvent.click(canvas.getByRole('button', { name: 'Submit' }));
await expect(canvas.getByText('Success!')).toBeInTheDocument();
},
};
Visual Regression Testing
# Chromatic — visual diff on every commit
npm install --save-dev chromatic
npx chromatic --project-token=YOUR_TOKEN
Run Storybook
npm run storybook # Dev at localhost:6006
npm run build-storybook # Static build for deployment
The Ship Fast Skill Pack includes a /test skill that generates Storybook stories alongside component tests. $49 at whoffagents.com.
Top comments (0)