Agent skill
storybook
Document and test React components with Storybook. Covers story writing, controls, args, decorators, play functions, and visual testing. Use for component documentation, design systems, isolated development, and interaction testing.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/other/other/storybook
SKILL.md
Storybook
Build and document UI components in isolation with interactive stories.
Instructions
- Write stories for all components - Each component should have a story file
- Use args for props - Define props through args for interactive controls
- Add decorators - Wrap stories with providers and layout wrappers
- Document with MDX - Write component documentation alongside stories
- Test interactions - Use play functions for interaction testing
Setup
# Initialize Storybook in existing project
npx storybook@latest init
# Start Storybook
npm run storybook
Configuration
// .storybook/main.ts
import type { StorybookConfig } from '@storybook/react-vite';
const config: StorybookConfig = {
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
addons: [
'@storybook/addon-links',
'@storybook/addon-essentials',
'@storybook/addon-interactions',
'@storybook/addon-a11y',
],
framework: {
name: '@storybook/react-vite',
options: {},
},
docs: {
autodocs: 'tag',
},
};
export default config;
Writing Stories
Basic Story Structure
// Button.stories.tsx
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';
const meta: Meta<typeof Button> = {
title: 'Components/Button',
component: Button,
tags: ['autodocs'],
parameters: {
layout: 'centered',
},
argTypes: {
variant: {
control: 'select',
options: ['primary', 'secondary', 'danger', 'ghost'],
description: 'The visual style of the button',
},
size: {
control: 'radio',
options: ['sm', 'md', 'lg'],
},
disabled: {
control: 'boolean',
},
onClick: { action: 'clicked' },
},
};
export default meta;
type Story = StoryObj<typeof Button>;
export const Primary: Story = {
args: {
children: 'Primary Button',
variant: 'primary',
},
};
export const Secondary: Story = {
args: {
children: 'Secondary Button',
variant: 'secondary',
},
};
export const Disabled: Story = {
args: {
children: 'Disabled Button',
disabled: true,
},
};
Multiple Variants
export const AllVariants: Story = {
render: () => (
<div className="flex flex-wrap gap-4">
<Button variant="primary">Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="danger">Danger</Button>
<Button variant="ghost">Ghost</Button>
</div>
),
};
export const AllSizes: Story = {
render: () => (
<div className="flex items-center gap-4">
<Button size="sm">Small</Button>
<Button size="md">Medium</Button>
<Button size="lg">Large</Button>
</div>
),
};
With Args
// args allow interactive control in Storybook UI
export const Playground: Story = {
args: {
children: 'Click me',
variant: 'primary',
size: 'md',
disabled: false,
loading: false,
},
};
Decorators
Global Decorators
// .storybook/preview.tsx
import type { Preview } from '@storybook/react';
import { ThemeProvider } from '../src/providers/ThemeProvider';
import '../src/styles/globals.css';
const preview: Preview = {
decorators: [
(Story) => (
<ThemeProvider>
<div className="p-4">
<Story />
</div>
</ThemeProvider>
),
],
parameters: {
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/i,
},
},
},
};
export default preview;
Story-Level Decorators
export const WithDarkBackground: Story = {
decorators: [
(Story) => (
<div className="bg-gray-900 p-8">
<Story />
</div>
),
],
args: {
children: 'Dark Mode Button',
variant: 'primary',
},
};
Interaction Testing
Play Functions
import { within, userEvent, expect } from '@storybook/test';
export const ClickInteraction: Story = {
args: {
children: 'Click me',
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const button = canvas.getByRole('button', { name: /click me/i });
await userEvent.click(button);
// Assertions
await expect(button).toBeVisible();
},
};
export const FormSubmission: Story = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
// Fill form fields
await userEvent.type(
canvas.getByLabelText(/email/i),
'[email protected]'
);
await userEvent.type(
canvas.getByLabelText(/password/i),
'password123'
);
// Submit form
await userEvent.click(canvas.getByRole('button', { name: /submit/i }));
// Check result
await expect(canvas.getByText(/success/i)).toBeInTheDocument();
},
};
Component Documentation
MDX Documentation
{/* Button.mdx */}
import { Meta, Story, Canvas, Controls, Source } from '@storybook/blocks';
import * as ButtonStories from './Button.stories';
<Meta of={ButtonStories} />
# Button
Buttons trigger actions or navigation. Use the appropriate variant
for the action's importance and context.
## Usage Guidelines
- Use **Primary** for the main action on a page
- Use **Secondary** for less important actions
- Use **Danger** only for destructive actions
- Limit to one primary button per section
## Examples
### Default
<Canvas of={ButtonStories.Primary} />
### All Variants
<Canvas of={ButtonStories.AllVariants} />
## Props
<Controls />
## Accessibility
- Buttons have proper focus states
- Loading state disables interaction and shows spinner
- Use `aria-label` for icon-only buttons
## Code
<Source of={ButtonStories.Primary} />
Inline Stories in MDX
import { Canvas, Meta } from '@storybook/blocks';
import { Button } from './Button';
<Meta title="Guide/Button Usage" />
# Using Buttons
Here's how to use buttons in different contexts:
<Canvas>
<Button variant="primary">Save Changes</Button>
<Button variant="secondary">Cancel</Button>
</Canvas>
Parameters
Layout
export const Centered: Story = {
parameters: {
layout: 'centered', // centered | fullscreen | padded
},
};
Backgrounds
export const OnDark: Story = {
parameters: {
backgrounds: {
default: 'dark',
},
},
};
Viewport
export const Mobile: Story = {
parameters: {
viewport: {
defaultViewport: 'mobile1',
},
},
};
Addons
Accessibility Addon
// Automatically checks accessibility
export const AccessibleButton: Story = {
args: {
children: 'Accessible',
'aria-label': 'Accessible button description',
},
parameters: {
a11y: {
config: {
rules: [
{ id: 'color-contrast', enabled: true },
],
},
},
},
};
Actions Addon
const meta: Meta<typeof Button> = {
component: Button,
argTypes: {
onClick: { action: 'clicked' },
onFocus: { action: 'focused' },
onBlur: { action: 'blurred' },
},
};
Project Structure
src/
├── components/
│ ├── Button/
│ │ ├── Button.tsx
│ │ ├── Button.test.tsx
│ │ ├── Button.stories.tsx
│ │ ├── Button.mdx
│ │ └── index.ts
│ ├── Card/
│ │ ├── Card.tsx
│ │ ├── Card.stories.tsx
│ │ └── index.ts
│ └── index.ts
├── .storybook/
│ ├── main.ts
│ └── preview.tsx
└── package.json
Best Practices
| Practice | Recommendation |
|---|---|
| File naming | Component.stories.tsx alongside component |
| Story naming | Use descriptive names like WithIcon, Disabled |
| Args | Prefer args over inline JSX for flexibility |
| Decorators | Use for providers, layout, theming |
| Play functions | Test interactions, not just rendering |
| Documentation | Write MDX docs for complex components |
When to Use
- Component library development
- Design system documentation
- Visual regression testing
- Isolated component development
- Team collaboration on UI
- Accessibility testing
Notes
- Storybook 7+ uses Component Story Format (CSF) 3
- Works with React, Vue, Angular, Svelte, and more
- Integrates with Chromatic for visual testing
- Supports TypeScript out of the box
- Hot module reloading for fast development
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?