DEV Community

Atlas Whoff
Atlas Whoff

Posted on

Storybook for Next.js: Component Development in Isolation

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
Enter fullscreen mode Exit fullscreen mode

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' },
};
Enter fullscreen mode Exit fullscreen mode

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 },
};
Enter fullscreen mode Exit fullscreen mode

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>
  ),
];
Enter fullscreen mode Exit fullscreen mode

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();
  },
};
Enter fullscreen mode Exit fullscreen mode

Visual Regression Testing

# Chromatic — visual diff on every commit
npm install --save-dev chromatic
npx chromatic --project-token=YOUR_TOKEN
Enter fullscreen mode Exit fullscreen mode

Run Storybook

npm run storybook     # Dev at localhost:6006
npm run build-storybook  # Static build for deployment
Enter fullscreen mode Exit fullscreen mode

The Ship Fast Skill Pack includes a /test skill that generates Storybook stories alongside component tests. $49 at whoffagents.com.

Top comments (0)