Story Structure (CSF 3.0)
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';
const meta: Meta = { title: 'Atoms/Button', component: Button, parameters: { layout: 'centered', }, tags: ['autodocs'], argTypes: { variant: { control: 'select', options: ['primary', 'secondary', 'ghost'], description: 'Visual style variant', }, size: { control: 'radio', options: ['sm', 'md', 'lg'], }, disabled: { control: 'boolean' }, onClick: { action: 'clicked' }, }, args: { children: 'Button', variant: 'primary', size: 'md', }, };
export default meta; type Story = StoryObj;
export const Primary: Story = { args: { variant: 'primary', }, };
export const Secondary: Story = { args: { variant: 'secondary', }, };
export const AllVariants: Story = { render: (args) => ( <div style={{ display: 'flex', gap: '1rem' }}> <Button {...args} variant="primary">Primary <Button {...args} variant="secondary">Secondary <Button {...args} variant="ghost">Ghost ), };
## File Naming
ComponentName/ ├── ComponentName.tsx ├── ComponentName.stories.tsx # Stories file ├── ComponentName.mdx # Optional: Extended docs
## Controls Configuration
| Control Type | Use For |
|--------------|---------|
| `select` | Enum with many options |
| `radio` | Enum with 2-4 options |
| `boolean` | True/false toggles |
| `text` | String inputs |
| `number` | Numeric values |
| `color` | Color pickers |
| `object` | Complex objects |
| `date` | Date values |
## Common Patterns
### Interactive Story with State
```tsx
export const WithState: Story = {
render: function Render(args) {
const [count, setCount] = useState(0);
return (
<Button {...args} onClick={() => setCount(c => c + 1)}>
Clicked {count} times
</Button>
);
},
};
Story with Decorators
const meta: Meta<typeof Card> = {
component: Card,
decorators: [
(Story) => (
<div style={{ padding: '2rem', background: '#f5f5f5' }}>
<Story />
</div>
),
],
};
Responsive Preview
export const Responsive: Story = {
parameters: {
viewport: {
viewports: {
mobile: { name: 'Mobile', styles: { width: '375px', height: '667px' } },
tablet: { name: 'Tablet', styles: { width: '768px', height: '1024px' } },
},
defaultViewport: 'mobile',
},
},
};
Organization by Atomic Design
Stories are grouped by title in the Storybook sidebar following Atomic Design:
// Atoms
title: 'Atoms/Button'
title: 'Atoms/Input'
title: 'Atoms/Icon'
// Molecules
title: 'Molecules/SearchField'
title: 'Molecules/FormField'
// Organisms
title: 'Organisms/Header'
title: 'Organisms/ProductCard'
// Templates
title: 'Templates/DashboardLayout'
// Pages
title: 'Pages/HomePage'
Story files are located directly with the components:
src/components/
├── atoms/
│ ├── Button/
│ │ ├── Button.tsx
│ │ ├── Button.module.css
│ │ ├── Button.stories.tsx # title: 'Atoms/Button'
│ │ └── index.ts
│ └── Input/
│ └── Input.stories.tsx # title: 'Atoms/Input'
├── molecules/
│ └── SearchField/
│ └── SearchField.stories.tsx # title: 'Molecules/SearchField'
└── organisms/
└── Header/
└── Header.stories.tsx # title: 'Organisms/Header'
Best Practices
- One story file per component
- Use
tags: ['autodocs']for auto-generated docs - Provide meaningful default args
- Show all variants in an overview story
- Use actions for event callbacks
- Document edge cases (loading, error, empty states)