
Storybook
- 51 installs
- 2 repo stars
- Updated August 3, 2026
- fandhe-ai/agent-reference-skills
Helps with ai & agent building tasks.
About
storybook is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- storybook
- AI & Agent Building
- AI-coding skill
Storybook by the numbers
- 51 all-time installs (skills.sh)
- Ranked #7,219 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 3, 2026 (Skillselion catalog sync)
npx skills add https://github.com/fandhe-ai/agent-reference-skills --skill storybookAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 51 |
|---|---|
| repo stars | ★ 2 |
| Last updated | August 3, 2026 |
| Repository | fandhe-ai/agent-reference-skills ↗ |
What it does
Helps with ai & agent building tasks.
Files
ArgTypes
Specify arg behavior, constrain acceptable values, and configure the Controls panel and documentation.
Overview
ArgTypes can be defined at three levels: story, component (meta), or project (preview.ts). Storybook automatically infers argTypes from the component using framework-specific tools (react-docgen, vue-docgen-api, compodoc, etc.). Manually specified values override inferred ones.
Usage
const meta = {
component: Button,
argTypes: {
variant: {
control: 'select',
options: ['primary', 'secondary', 'danger'],
description: 'Visual style of the button',
table: { category: 'Appearance' },
},
onClick: { action: 'clicked' },
disabled: { control: 'boolean' },
},
} satisfies Meta<typeof Button>;Properties
control
Configures the Controls panel UI. Can be a string shorthand or an object.
| Value | Renders |
|---|---|
'boolean' | Toggle |
'number' | Number input |
'range' | Slider |
'text' | Text input |
'color' | Color picker |
'date' | Date picker |
'select' | Select dropdown |
'multi-select' | Multi-select |
'radio' | Radio buttons |
'inline-radio' | Inline radio buttons |
'check' | Checkboxes |
'inline-check' | Inline checkboxes |
'object' | JSON editor |
'file' | File upload |
false | Disable control |
Object form options: type, accept (MIME types), labels, min, max, step, presetColors
description
string — Describes the arg's purpose in the docs panel.
if
Conditionally renders the control based on another arg or global value.
argTypes: {
secondaryLabel: {
if: { arg: 'variant', eq: 'secondary' },
},
}| Sub-field | Type | Description |
|---|---|---|
arg | string | Watch this arg name |
global | string | Watch this global name |
eq | any | Show when value equals |
neq | any | Show when value does not equal |
exists | boolean | Show when arg exists (or not) |
truthy | boolean | Show when arg is truthy (or falsy) |
mapping
Maps string option keys to actual values (useful for non-primitive types like JSX elements).
argTypes: {
icon: {
options: ['home', 'settings'],
mapping: { home: <HomeIcon />, settings: <SettingsIcon /> },
},
}name
string — Overrides the displayed argType name. Use cautiously to avoid confusion with actual prop names.
options
any[] — Array of allowed values. Used with control to determine the appropriate UI widget.
table
Documentation metadata for the Args table.
| Sub-field | Type | Description |
|---|---|---|
category | string | Group label |
subcategory | string | Nested group label |
defaultValue | { summary, detail } | Documented default value |
disable | boolean | Hide from tables |
type | { summary, detail } | Documented type information |
readonly | boolean | Mark as read-only |
type
Semantic type using SBType structure.
- Scalars:
'boolean' | 'string' | 'number' | 'function' | 'symbol' - Collections:
array,object,enum,union,intersection
Notes
defaultValueis deprecated — define defaults inargsinstead- Story-level argTypes override component-level which override project-level
Related
- CSF
- Parameters
CLI Options
All Storybook CLI commands and their available flags.
Overview
The Storybook CLI (storybook) is the primary tool for developing, building, and managing Storybook projects.
npm users: Prefix options with--separator:npm run storybook build -- -o ./dist
Commands
storybook dev
Compile and serve a live-reloading development build.
storybook dev [options]| Option | Type | Description |
|---|---|---|
-p, --port | number | Port to run on (default: 6006) |
-h, --host | string | Host to bind to |
-c, --config-dir | string | Config directory (default: .storybook) |
--loglevel | string | `trace \ |
--https | — | Serve over HTTPS |
--ssl-cert | string | SSL certificate path |
--ssl-key | string | SSL key path |
--ssl-ca | string | SSL CA path |
--smoke-test | — | Exit after successful startup |
--ci | — | CI mode — skip prompts, don't open browser |
--no-open | — | Prevent auto-opening browser |
--quiet | — | Suppress verbose output |
--debug | — | Output additional debug logs |
--initial-path | string | URL path to open in browser |
--preview-url | string | Override preview iframe URL |
--force-build-preview | — | Force rebuild of preview iframe |
--docs | — | Start in documentation mode |
--disable-telemetry | — | Disable telemetry collection |
--enable-crash-reports | — | Enable crash report submission |
---
storybook build
Compile Storybook for static deployment.
storybook build [options]| Option | Type | Description |
|---|---|---|
-o, --output-dir | string | Output directory for built files |
-c, --config-dir | string | Config directory |
--loglevel | string | `trace \ |
--quiet | — | Suppress verbose output |
--debug | — | Additional debug information |
--docs | — | Build in documentation mode |
--test | — | Optimize build for testing (removes UI features) |
--preview-url | string | Override preview iframe URL |
--force-build-preview | — | Force preview iframe rebuild |
--disable-telemetry | — | Disable telemetry |
---
storybook init
Install and configure Storybook in a project.
storybook[@version] init [options]| Option | Description |
|---|---|
-b, --builder | Specify builder (webpack5, vite, etc.) |
-f, --force | Overwrite existing config files |
-s, --skip-install | Skip dependency installation |
-t, --type | Framework type (react, angular, vue, etc.) |
-y, --yes | Skip prompts and auto-install |
--features [...values] | Install specific features (docs, test, a11y) |
--package-manager | Package manager (npm, yarn, pnpm) |
--no-dev | Complete init without running dev server |
---
storybook add
Install and configure a Storybook addon.
storybook add [addon] [options]| Option | Description |
|---|---|
-c, --config-dir | Config directory |
--package-manager | Package manager |
-s, --skip-postinstall | Skip post-install configuration |
---
storybook remove
Remove a Storybook addon from the project.
storybook remove [addon] [options]---
storybook upgrade
Upgrade Storybook to a newer version.
storybook[@version] upgrade [options]| Option | Description |
|---|---|
-c, --config-dir | Config directory (supports multiple) |
-n, --dry-run | Check upgrades without installing |
-s, --skip-check | Skip migration check |
-y, --yes | Skip prompts and auto-upgrade |
-f, --force | Force upgrade, skip autoblockers |
--package-manager | Package manager |
---
storybook migrate
Run codemods for version compatibility.
storybook[@version] migrate [codemod] [options]| Option | Description |
|---|---|
-n, --dry-run | Verify without applying changes |
-l, --list | List available codemods |
-g, --glob | Glob pattern for target files |
-p, --parser | jscodeshift parser (babel, babylon, flow, ts, tsx) |
-r, --rename [from-to] | Rename files with suffix |
---
storybook automigrate
Run automatic configuration migrations.
storybook[@version] automigrate [fixId] [options]| Option | Description |
|---|---|
-n, --dry-run | Check without applying |
-y, --yes | Auto-apply without prompting |
-l, --list | List available automigrations |
--renderer | Specify renderer (useful for monorepos) |
---
storybook doctor
Run health checks for common project issues.
storybook doctor [options]---
storybook ai
Helpers for AI agents. Exposes subcommands that generate AI-friendly instructions for automating Storybook tasks.
storybook ai <subcommand> [options]storybook ai setup
Generates a detailed, project-aware Markdown prompt that instructs an AI agent to configure Storybook and write initial stories.
| Option | Description |
|---|---|
--output <path> | Write prompt to file |
-c, --config-dir [dir] | Config directory (default: .storybook) |
--package-manager <type> | Force package manager (npm, yarn, pnpm) |
--disable-telemetry | Disable telemetry |
--debug | Output debug logs |
--loglevel [level] | Log level |
--logfile [path] | Write logs to file |
---
storybook info
Report environment debugging information (OS, Node, npm, installed Storybook packages).
storybook info---
storybook index
Build an index.json listing all stories and docs entries.
storybook index [options]| Option | Description |
|---|---|
-o, --output-file | JSON output file path |
-c, --config-dir | Config directory |
---
storybook sandbox
Generate a local sandbox project for testing Storybook features.
storybook[@version] sandbox [framework-filter] [options]| Option | Description |
|---|---|
-o, --output | Output directory |
--no-init | Generate without initializing Storybook |
Notes
- Telemetry collects anonymous usage data; opt out with
--disable-telemetryon any command storybook initis also available ascreate storybook[@version]
Related
- CSF
- Frameworks
CSF — Component Story Format
An open standard for writing Storybook stories based on ES6 modules, portable beyond Storybook itself.
Overview
CSF files export a required default export (the meta object) describing the component, and one or more named exports (the stories). Storybook reads these exports to build the sidebar navigation and render each story. CSF 3 (current) uses plain objects instead of functions, supports default render functions, and enables automatic title generation from file paths.
Usage
Minimal CSF 3 file
// Button.stories.ts
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';
const meta = {
component: Button,
} satisfies Meta<typeof Button>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Primary: Story = {
args: { label: 'Button', primary: true },
};Meta (default export) fields
| Field | Type | Description |
|---|---|---|
component | ComponentType | The component being documented (required) |
title | string | Sidebar path, e.g. 'UI/Button'. Auto-generated if omitted |
args | Partial<ComponentArgs> | Default args applied to all stories |
argTypes | ArgTypes | Metadata for each arg (controls, mapping, etc.) |
parameters | Parameters | Static addon/feature configuration |
decorators | Decorator[] | Wrappers applied to all stories |
render | (args, context) => JSX | Custom render function for all stories |
includeStories | `string[] \ | RegExp` |
excludeStories | `string[] \ | RegExp` |
tags | string[] | Tags for filtering and organization |
Story (named export) fields
| Field | Type | Description |
|---|---|---|
args | Partial<ComponentArgs> | Story-specific args, merged over meta args |
render | (args, context) => JSX | Custom render function overriding meta render |
play | async (context) => void | Interaction script run after story renders |
decorators | Decorator[] | Story-specific wrappers |
parameters | Parameters | Story-specific addon configuration |
name | string | Display name override (use for reserved words or special characters) |
tags | string[] | Story-level tags |
Custom render function
export const WithRender: Story = {
args: { label: 'Hello', onClick: action('clicked') },
render: ({ label, onClick }) => <Button label={label} onClick={onClick} />,
};Play function
export const FilledForm: Story = {
play: async ({ canvas, userEvent }) => {
await userEvent.type(canvas.getByTestId('email'), 'test@example.com');
await userEvent.click(canvas.getByRole('button'));
await expect(canvas.getByText('Success!')).toBeInTheDocument();
},
};Excluding non-story exports
const meta = {
component: MyComponent,
excludeStories: /.*Data$/, // exports ending in "Data" are not stories
} satisfies Meta<typeof MyComponent>;
export const mockData = { … }; // excluded
export const Primary: Story = { … }; // includedNotes
- Named export identifiers are converted to "start case" for display:
someStoryName→ "Some Story Name". Usenameto override. - CSF 3 stories are plain objects; Storybook provides default render functions per framework, so explicit
renderis usually unnecessary. - Upgrade from CSF 2:
npx storybook migrate csf-2-to-3 --glob="**/*.stories.tsx". - CSF is framework-agnostic — the same format works with React, Vue, Angular, Svelte, etc.
Related
- README
ArgTypes
A static table that displays argument type definitions for a component's interface in documentation.
Import
import { ArgTypes } from '@storybook/addon-docs/blocks';Props
| Name | Type | Description |
|---|---|---|
of | Story export or CSF file exports | Specifies which story to retrieve arg types from; uses primary story if CSF file is provided |
exclude | `string[] \ | RegExp` |
include | `string[] \ | RegExp` |
sort | `'none' \ | 'alpha' \ |
Usage
import { Meta, ArgTypes } from '@storybook/addon-docs/blocks';
import * as ButtonStories from './Button.stories';
<Meta of={ButtonStories} />
<ArgTypes of={ButtonStories} exclude={['style']} />Notes
- Unlike
Controls,ArgTypesrenders a static table without interactive value editing - Defaults can be configured via
parameters.docs.argTypesat project, component, or story level - Props and parameters configurations are interchangeable
Related
- controls.md
- stories.md
Canvas
A wrapper around a Story block with an interactive toolbar that displays stories and automatically provides source code snippets.
Import
import { Canvas } from '@storybook/addon-docs/blocks';Props
| Name | Type | Default | Description |
|---|---|---|---|
of | Story export | — | Specifies which story's source is displayed |
sourceState | `'hidden' \ | 'shown' \ | 'none'` |
layout | `'centered' \ | 'fullscreen' \ | 'padded'` |
withToolbar | boolean | — | Whether to render the interaction toolbar |
className | string | — | HTML class(es) for custom styling |
additionalActions | Array<{ title: string; onClick: () => void }> | — | Custom buttons added to the toolbar's bottom-right corner |
meta | CSF file exports | — | Associates the story with an alternate CSF file |
source | Source block props | — | Configuration for code display (format, language, type) |
story | Story block props | — | Configuration for inline rendering (height, autoplay) |
Usage
import { Meta, Canvas } from '@storybook/addon-docs/blocks';
import * as ButtonStories from './Button.stories';
<Meta of={ButtonStories} />
<Canvas of={ButtonStories.Primary} sourceState="shown" /><Canvas
of={ButtonStories.Primary}
additionalActions={[
{
title: 'Open in GitHub',
onClick: () => window.open('https://github.com/...', '_blank'),
},
]}
/>Notes
- The source block inside Canvas always renders in dark mode
- Passing arbitrary components as children is deprecated; only a single story is supported
- Configure defaults via
parameters.docs.canvas
Related
- story.md
- source.md
ColorPalette / ColorItem
A doc block that documents color-related items such as color swatches used throughout a project.
Import
import { ColorPalette, ColorItem } from '@storybook/addon-docs/blocks';Props
ColorPalette
| Name | Type | Description |
|---|---|---|
children | React.ReactNode | Accepts only ColorItem children |
ColorItem
| Name | Type | Description |
|---|---|---|
title | string | (Required) Name/label for the color grouping |
subtitle | string | (Required) Additional context or category description |
colors | `string[] \ | { [key: string]: string }` |
Usage
import { Meta, ColorPalette, ColorItem } from '@storybook/addon-docs/blocks';
<Meta title="Colors" />
<ColorPalette>
<ColorItem
title="theme.color.primary"
subtitle="Coral"
colors={{ WildWatermelon: '#FF4785' }}
/>
<ColorItem
title="theme.color.positive"
subtitle="Green"
colors={{
Apple: 'rgba(102,191,60,1)',
Apple80: 'rgba(102,191,60,.8)',
}}
/>
</ColorPalette>Notes
colorsaccepts any valid CSS color format: hex, RGB, HSL, gradients ('linear-gradient(to right, white, black)')- Particularly useful for design system color documentation
Related
- typeset.md
- icon-gallery.md
Controls
A dynamic table displaying component arguments with functioning UI controls for interactive documentation and argument modification.
Import
import { Controls } from '@storybook/addon-docs/blocks';Props
| Name | Type | Description |
|---|---|---|
of | Story export or CSF file exports | Specifies which story to retrieve controls from; uses primary story if CSF file is provided |
exclude | `string[] \ | RegExp` |
include | `string[] \ | RegExp` |
sort | `'none' \ | 'alpha' \ |
Usage
import { Meta, Canvas, Controls } from '@storybook/addon-docs/blocks';
import * as ButtonStories from './Button.stories';
<Meta of={ButtonStories} />
<Canvas of={ButtonStories.Primary} />
<Controls of={ButtonStories.Primary} />// Configure defaults via parameters
const meta = {
component: Button,
parameters: {
docs: {
controls: { exclude: ['style'] },
},
},
};Notes
- Controls only work when inline stories are not turned off
- For static (non-interactive) arg documentation, use
ArgTypesinstead - Configuration available at project, component, or story levels via
parameters.docs.controls
Related
- arg-types.md
- canvas.md
Description
Displays component, story, or meta descriptions sourced from JSDoc comments or parameters as rendered markdown.
Import
import { Description } from '@storybook/addon-docs/blocks';Props
| Name | Type | Description |
|---|---|---|
of | Story export or CSF file exports | Specifies the source for pulling descriptions (story or meta) |
Usage
import { Meta, Description } from '@storybook/addon-docs/blocks';
import * as ButtonStories from './Button.stories';
<Meta of={ButtonStories} />
{/* Shows meta/component description */}
<Description of={ButtonStories} />
{/* Shows a specific story's description */}
<Description of={ButtonStories.Primary} />Notes
Description lookup order for stories: 1. parameters.docs.description.story on the story 2. JSDoc comment above the story export
Description lookup order for component/meta: 1. parameters.docs.description.component in the meta 2. JSDoc comment above the meta 3. JSDoc comment above the component
- Markdown is rendered in descriptions
- Parameter-based descriptions override JSDoc comments when both exist
Related
- subtitle.md
- title.md
IconGallery / IconItem
A doc block that displays icon components in a neat grid layout for documentation purposes.
Import
import { IconGallery, IconItem } from '@storybook/addon-docs/blocks';Props
IconGallery
| Name | Type | Description |
|---|---|---|
children | React.ReactNode | Accepts only IconItem children |
IconItem
| Name | Type | Description |
|---|---|---|
name | string | (Required) Sets the display name of the icon |
children | React.ReactNode | The icon component to display |
Usage
import { Meta, IconGallery, IconItem } from '@storybook/addon-docs/blocks';
import { Icon } from './Icon';
<Meta title="Iconography" />
<IconGallery>
<IconItem name="mobile">
<Icon name="mobile" />
</IconItem>
<IconItem name="user">
<Icon name="user" />
</IconItem>
</IconGallery>{/* Automated with iteration for large icon sets */}
<IconGallery>
{Object.keys(icons).map((icon) => (
<IconItem key={icon} name={icon}>
<Icon icon={icon} />
</IconItem>
))}
</IconGallery>Notes
- Best suited for documenting React icon components
- Renders icons in a grid layout with automatic layout management
Related
- color-palette.md
- typeset.md
Markdown
A doc block that imports and displays plain markdown content within MDX files.
Import
import { Markdown } from '@storybook/addon-docs/blocks';Props
| Name | Type | Description |
|---|---|---|
children | string | The markdown-formatted string to parse and display |
options | object | Configuration options passed to the underlying markdown-to-jsx library |
Usage
import ReadMe from './README.md?raw';
import { Markdown } from '@storybook/addon-docs/blocks';
# A header
<Markdown>{ReadMe}</Markdown>Notes
- Always use the
?rawsuffix when importing.mdfiles to prevent MDX2 from evaluating them as JSX - MDX2 has stricter syntax rules than plain markdown; curly braces and angle brackets can cause parse errors when not wrapped
- Direct markdown string content in MDX gets wrapped in
<p>tags automatically; theMarkdownblock avoids this issue
Related
- unstyled.md
Meta
Attaches an MDX documentation page to component stories and controls the sidebar entry location. Renders no visible output.
Import
import { Meta } from '@storybook/addon-docs/blocks';Props
| Name | Type | Description |
|---|---|---|
of | CSF file exports | Specifies which CSF file is attached; pass the full set of exports |
name | string | Customizes the sidebar entry name; enables multiple MDX files per component |
title | string | Sets the title of an unattached MDX file for sidebar placement |
isTemplate | boolean | When true, marks the file as an autodocs template and prevents it from being indexed |
Usage
import { Meta } from '@storybook/addon-docs/blocks';
import * as ButtonStories from './Button.stories';
<Meta of={ButtonStories} />{/* Unattached docs page with custom sidebar location */}
<Meta title="Design System/Overview" />Notes
Metarenders no visible output; it only provides metadata- Attached docs (using
of) appear in the sidebar under the component's stories - Unattached docs (using
title) appear at any position in the sidebar hierarchy - Use
nameto attach multiple MDX files to the same component
Related
- title.md
- primary.md
Primary
Renders the first story defined in a CSF file, typically positioned beneath the title in documentation.
Import
import { Primary } from '@storybook/addon-docs/blocks';Props
| Name | Type | Description |
|---|---|---|
of | CSF file exports | Specifies which CSF file to use; pass the full set of exports (not the default export) |
Usage
import { Meta, Primary } from '@storybook/addon-docs/blocks';
import * as ButtonStories from './Button.stories';
<Meta of={ButtonStories} />
<Primary />Notes
- Renders the first story defined in the stories file, wrapped in a
Storyblock - Pass the complete CSF file exports to
of, not thedefaultexport - Typically placed immediately under the documentation title
- When
Metais attached viaof,Primarycan be used without theofprop
Related
- story.md
- canvas.md
- meta.md
Doc Blocks
Storybook's built-in doc block components and hooks for building MDX documentation pages.
| Name | Description | Path |
|---|---|---|
| ArgTypes | Static table of argument type definitions for a component's interface | ./arg-types.md |
| Canvas | Story wrapper with interactive toolbar and automatic source code display | ./canvas.md |
| ColorPalette / ColorItem | Grid of color swatches for documenting a project's color system | ./color-palette.md |
| Controls | Dynamic interactive table for editing component arguments in docs | ./controls.md |
| Description | Renders component, story, or meta descriptions from JSDoc or parameters | ./description.md |
| IconGallery / IconItem | Grid layout for displaying and documenting icon components | ./icon-gallery.md |
| Markdown | Imports and displays plain markdown content inside MDX files | ./markdown.md |
| Meta | Attaches an MDX file to component stories; controls sidebar placement | ./meta.md |
| Primary | Renders the first story in a CSF file | ./primary.md |
| Source | Renders code snippets with syntax highlighting in documentation | ./source.md |
| Stories | Renders the complete collection of stories from a CSF file | ./stories.md |
| Story | Renders a single named story within MDX documentation | ./story.md |
| Subtitle | Secondary heading block for documentation entries | ./subtitle.md |
| TableOfContents | Fixed sidebar TOC generated from page headings | ./table-of-contents.md |
| Title | Primary heading block for documentation entries | ./title.md |
| Typeset | Typography sample display for fonts, weights, and sizes | ./typeset.md |
| Unstyled | Disables Storybook's default MDX styles for wrapped content | ./unstyled.md |
| useOf | Hook to resolve story/meta/component exports for custom doc blocks | ./use-of.md |
Source
Renders code snippets directly in Storybook documentation.
Import
import { Source } from '@storybook/addon-docs/blocks';Props
| Name | Type | Description |
|---|---|---|
of | Story export | References which story's source to render |
code | string | Provides raw source code to display |
language | `'jsx' \ | 'tsx' \ |
dark | boolean | Displays the snippet in dark mode |
excludeDecorators | boolean | Controls whether decorators appear in the code snippet |
transform | `(code: string, storyContext: StoryContext) => string \ | Promise<string>` |
type | `'auto' \ | 'code' \ |
Usage
import { Meta, Source } from '@storybook/addon-docs/blocks';
import * as ButtonStories from './Button.stories';
<Meta of={ButtonStories} />
<Source of={ButtonStories.Primary} />{/* Render arbitrary code */}
<Source language="tsx" code={`const x = <Button label="Hello" />;`} />Notes
- When rendered inside a
Canvasblock, Source always uses dark mode regardless of thedarkprop - Dynamic snippets require stories that use
argsand have theStoryblock rendered alongside - Configure defaults via
parameters.docs.sourceat story, component, or project level
Related
- canvas.md
- story.md
Stories
Renders the complete collection of stories from a CSF file in documentation.
Import
import { Stories } from '@storybook/addon-docs/blocks';Props
| Name | Type | Default | Description |
|---|---|---|---|
includePrimary | boolean | true | Determines if the collection includes the primary (first) story |
title | string | 'Stories' | Sets the heading content preceding the story collection |
Usage
import { Meta, Stories } from '@storybook/addon-docs/blocks';
import * as ButtonStories from './Button.stories';
<Meta of={ButtonStories} />
<Stories />Notes
- If a stories file contains only one story and
includePrimary={true},Storiesrenders nothing to avoid a confusing duplicate - Requires
Metato be configured with theofprop pointing to the stories file - Use
titleto customize the section heading above the story list
Related
- story.md
- primary.md
Story
Renders a single story from a CSF file within MDX documentation with all annotations applied.
Import
import { Story } from '@storybook/addon-docs/blocks';Props
| Name | Type | Default | Description |
|---|---|---|---|
of | Story export | — | (Required) Specifies which story is rendered |
autoplay | boolean | parameters.docs.story.autoplay | Whether the story's play function runs automatically |
inline | boolean | true (framework-dependent) | Renders inline in the docs frame vs. in an iframe |
height | string | parameters.docs.story.height | Sets the minimum height when rendering in iframe or inline |
meta | CSF file exports | — | Specifies the CSF file for non-attached stories |
Usage
import { Meta, Story } from '@storybook/addon-docs/blocks';
import * as ButtonStories from './Button.stories';
<Meta of={ButtonStories} />
<Story of={ButtonStories.Primary} />Notes
- All stories in a docs entry render simultaneously; play functions may interact with each other
- Stories using
mountinside their play function requireautoplay={true}to render in docs - Setting
inline={false}prevents controls from updating the story within the documentation page - For a story with a border and source snippet, prefer
CanvasoverStory
Related
- canvas.md
- stories.md
- primary.md
Subtitle
A secondary heading block for documentation entries in Storybook.
Import
import { Subtitle } from '@storybook/addon-docs/blocks';Props
| Name | Type | Default | Description |
|---|---|---|---|
children | `JSX.Element \ | string` | parameters.docs.subtitle |
of | CSF file exports | — | Specifies which meta's subtitle to display |
Usage
import { Subtitle } from '@storybook/addon-docs/blocks';
<Subtitle>This is the subtitle</Subtitle>Notes
- Pairs with
Titlefor hierarchical documentation structure - Falls back to
parameters.docs.subtitlewhen no children are provided
Related
- title.md
- description.md
TableOfContents
Renders an interactive table of contents for documentation pages, displayed as a fixed sidebar on the right side of larger screens.
Import
import { TableOfContents } from '@storybook/blocks';Configuration
TableOfContents is configured via parameters.docs.toc, not direct JSX props.
| Parameter | Type | Default | Description |
|---|---|---|---|
disable | boolean | false | Hides the TOC while preserving layout space |
headingSelector | string | 'h3' | CSS selector for heading levels to include |
contentsSelector | string | '.sbdocs-content' | Container element to search for headings |
ignoreSelector | string | '.docs-story *, .skip-toc' | Selector for headings to exclude |
title | `string \ | null \ | ReactElement` |
unsafeTocbotOptions | object | — | Additional options passed directly to the Tocbot library |
Usage
// .storybook/preview.ts — enable globally
import type { Preview } from '@storybook/your-framework';
const preview: Preview = {
parameters: {
docs: {
toc: true,
},
},
};
export default preview;// Disable for a specific component
const meta = {
component: MyComponent,
parameters: {
docs: {
toc: { disable: true },
},
},
};Notes
- Hidden on screens narrower than 768px
- Add the
skip-tocCSS class to individual headings to exclude them from the TOC - The block is automatically rendered by Storybook's docs container; it does not need to be added manually to MDX
Related
- meta.md
- title.md
Title
The primary heading block for documentation entries, typically displaying the component or page name.
Import
import { Title } from '@storybook/addon-docs/blocks';Props
| Name | Type | Description |
|---|---|---|
children | `JSX.Element \ | string` |
of | CSF file exports | Specifies which meta's title to display |
Usage
import { Title } from '@storybook/addon-docs/blocks';
<Title>My Component</Title>Notes
- Typically appears at the top of documentation pages
- When used with an attached CSF file, automatically derives content from story metadata
- Auto-titling trims the hierarchical path to the last segment per CSF 3.0 conventions
Related
- subtitle.md
- meta.md
Typeset
A documentation block that displays typography samples to showcase fonts, weights, and sizes used in a project.
Import
import { Typeset } from '@storybook/addon-docs/blocks';Props
| Name | Type | Description |
|---|---|---|
fontFamily | string | The font family to display |
fontSizes | `(string \ | number)[]` |
fontWeight | number | Weight of the font to display |
sampleText | string | Text string to display at each size |
Usage
import { Meta, Typeset } from '@storybook/addon-docs/blocks';
export const typography = {
type: { primary: '"Nunito Sans", sans-serif' },
weight: { regular: '400', bold: '700' },
size: { s1: 12, m1: 20, l1: 32 },
};
<Meta title="Typography" />
<Typeset
fontFamily={typography.type.primary}
fontSizes={[typography.size.s1, typography.size.m1, typography.size.l1]}
fontWeight={Number(typography.weight.bold)}
sampleText="The quick brown fox jumps over the lazy dog"
/>Notes
fontSizesexpects numeric pixel values; wrap object-sourced values withNumber()if needed- Designed for typography system documentation in design documentation pages
Related
- color-palette.md
- icon-gallery.md
Unstyled
Disables Storybook's default MDX documentation styles for the content wrapped inside it.
Import
import { Unstyled } from '@storybook/addon-docs/blocks';Props
| Name | Type | Description |
|---|---|---|
children | React.ReactNode | Content to which default docs styles should not be applied |
Usage
import { Meta, Unstyled } from '@storybook/addon-docs/blocks';
import { Header } from './Header';
<Meta title="Example" />
> This blockquote will be styled by Storybook defaults.
<Unstyled>
> This blockquote will NOT be styled.
<Header />
</Unstyled>Notes
- Apply
Unstyledat the root level of MDX, not nested within other elements; nesting causes CSS inheritance issues StoryandCanvasblocks are already unstyled; wrapping them inUnstyledis unnecessary- Inherited CSS properties (e.g.,
color) will still apply to child components when nested
Related
- markdown.md
- canvas.md
useOf
A React hook that resolves story, meta, or component exports into their annotated forms for building custom doc blocks.
Import
import { useOf } from '@storybook/addon-docs/blocks';Signature
function useOf(
moduleExportOrType: ModuleExport | 'story' | 'meta' | 'component',
validTypes?: Array<'story' | 'meta' | 'component'>
): ResolvedOfParameters
| Name | Type | Description |
|---|---|---|
moduleExportOrType | `ModuleExport \ | 'story' \ |
validTypes | `Array<'story' \ | 'meta' \ |
Return Value
| Type resolved | Shape |
|---|---|
| Story | { type: 'story', story: PreparedStory } |
| Meta | { type: 'meta', csfFile: CSFFile, preparedMeta: PreparedMeta } |
| Component | { type: 'component', component: Component, projectAnnotations: NormalizedProjectAnnotations } |
Usage
import { useOf } from '@storybook/addon-docs/blocks';
export const StoryName = ({ of }) => {
const resolvedOf = useOf(of || 'story', ['story', 'meta']);
switch (resolvedOf.type) {
case 'story':
return <h1>{resolvedOf.story.name}</h1>;
case 'meta':
return <h1>{resolvedOf.preparedMeta.title}</h1>;
}
return null;
};Notes
- Most built-in doc blocks (
Description,Canvas, etc.) useuseOfinternally - String references (
'story','meta','component') only work in attached doc mode - Use
validTypesto guard against receiving an unexpected export type
Related
- meta.md
- story.md
addons
Registers addon packages that extend Storybook's functionality.
Type
type addons = (string | { name: string; options?: AddonOptions })[]Usage
// .storybook/main.ts
import { fileURLToPath } from 'node:url';
import type { StorybookConfig } from '@storybook/your-framework';
const config: StorybookConfig = {
framework: '@storybook/your-framework',
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
addons: [
'@storybook/addon-docs',
{
name: '@storybook/addon-styling-webpack',
options: {
rules: [{ test: /\.css$/, use: ['style-loader', 'css-loader'] }],
},
},
],
};
export default config;Options
| Name | Type | Description |
|---|---|---|
name | string | Package identifier for the addon |
options | AddonOptions | Addon-specific configuration (varies per addon) |
Notes
- Use a simple string for addons that need no configuration
- Consult each addon's documentation for supported
options
Related
- features.md
- build.md
babel
Customizes Storybook's Babel configuration for Webpack-based projects.
Type
type babel = (
config: Babel.Config,
options: { configType: 'DEVELOPMENT' | 'PRODUCTION' }
) => Babel.Config | Promise<Babel.Config>Usage
// .storybook/main.ts
import type { StorybookConfig } from '@storybook/your-framework';
const config: StorybookConfig = {
framework: '@storybook/your-framework',
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
async babel(config, { configType }) {
if (configType === 'DEVELOPMENT') {
// development-only modifications
}
if (configType === 'PRODUCTION') {
// production-only modifications
}
return config;
},
};
export default config;Options
| Name | Type | Description |
|---|---|---|
config | Babel.Config | The existing Babel configuration to modify |
options.configType | `'DEVELOPMENT' \ | 'PRODUCTION'` |
Notes
- Only applicable when
@storybook/addon-webpack5-compiler-babeladdon is enabled - If a
.babelrcfile exists, it is auto-detected and used without additional configuration - Addon authors should use
babelDefaultinstead (runs before user presets)
Related
- swc.md
- webpack-final.md
build
Optimizes Storybook's production build output, particularly for testing scenarios.
Type
type TestBuildConfig = {
test?: TestBuildFlags;
};
type TestBuildFlags = {
disableBlocks?: boolean;
disabledAddons?: string[];
disableMDXEntries?: boolean;
disableAutoDocs?: boolean;
disableDocgen?: boolean;
disableSourcemaps?: boolean;
disableTreeShaking?: boolean;
};Usage
// .storybook/main.ts
import type { StorybookConfig } from '@storybook/your-framework';
const config: StorybookConfig = {
framework: '@storybook/your-framework',
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
addons: ['@storybook/addon-a11y', '@storybook/addon-vitest'],
build: {
test: {
disableBlocks: false,
disabledAddons: ['@storybook/addon-a11y'],
disableAutoDocs: false,
},
},
};
export default config;Options
| Name | Type | Description |
|---|---|---|
test.disableBlocks | boolean | Excludes @storybook/addon-docs/blocks from the build |
test.disabledAddons | string[] | List of addons to exclude from the build |
test.disableMDXEntries | boolean | Removes user-written MDX documentation entries |
test.disableAutoDocs | boolean | Prevents autodocs-generated documentation |
test.disableDocgen | boolean | Disables automatic argType/prop inference |
test.disableSourcemaps | boolean | Overrides default source map generation |
test.disableTreeShaking | boolean | Disables tree shaking during build |
Notes
- These options activate automatically when using
storybook build --test - Override only when debugging build issues or disabling specific features for testing
Related
- addons.md
core
Configures Storybook's internal features including the dev server, build system, and telemetry.
Type
{
allowedHosts?: string[] | true;
builder?: string | { name: string; options?: BuilderOptions };
channelOptions?: { maxDepth?: number };
crossOriginIsolated?: boolean;
disableProjectJson?: boolean;
disableTelemetry?: boolean;
disableWebpackDefaults?: boolean;
disableWhatsNewNotifications?: boolean;
enableCrashReports?: boolean;
renderer?: RendererName;
}Usage
// .storybook/main.ts
import type { StorybookConfig } from '@storybook/your-framework';
const config: StorybookConfig = {
framework: '@storybook/your-framework',
stories: ['../src/**/*.stories.@(js|jsx|ts|tsx)'],
core: {
allowedHosts: ['storybook.example.local'],
disableTelemetry: true,
disableWhatsNewNotifications: true,
},
};
export default config;Options
| Name | Type | Default | Description |
|---|---|---|---|
allowedHosts | `string[] \ | true` | [] |
builder | `string \ | { name, options? }` | — |
channelOptions.maxDepth | number | 3 | Max nesting depth for serialized objects in manager-preview channel |
crossOriginIsolated | boolean | false | Enables CORS headers for SharedArrayBuffer support |
disableProjectJson | boolean | false | Prevents project.json metadata file generation |
disableTelemetry | boolean | false | Disables telemetry data collection |
disableWebpackDefaults | boolean | false | Disables Storybook's default Webpack configuration |
disableWhatsNewNotifications | boolean | false | Hides "What's New" UI notifications |
enableCrashReports | boolean | false | Includes crash reports in telemetry |
renderer | RendererName | — | Specifies the rendering engine |
Notes
allowedHosts: truedisables security validation — do not use in productionchannelOptions.maxDepthlarger values may cause serialization slowdownsframework.options.builderis preferred overcore.builder.options
Related
- framework.md
- vite-final.md
- webpack-final.md
docs
Controls Storybook's auto-generated documentation features.
Type
{
defaultName?: string;
docsMode?: boolean;
}Usage
// .storybook/main.ts
import type { StorybookConfig } from '@storybook/your-framework';
const config: StorybookConfig = {
framework: '@storybook/your-framework',
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
docs: {
defaultName: 'Documentation',
},
};
export default config;Options
| Name | Type | Default | Description |
|---|---|---|---|
defaultName | string | 'Docs' | Name used for generated documentation pages in the sidebar |
docsMode | boolean | — | Restricts the sidebar to show only documentation pages |
Notes
docsModeis usually set via the--docsCLI flag rather than directly in config
Related
- features.md
- typescript.md
env
Defines custom environment variables accessible throughout your Storybook instance.
Type
type env = (config: { [key: string]: string }) => { [key: string]: string }Usage
// .storybook/main.ts
import type { StorybookConfig } from '@storybook/your-framework';
const config: StorybookConfig = {
framework: '@storybook/your-framework',
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
env: (config) => ({
...config,
EXAMPLE_VAR: 'An environment variable configured in Storybook',
}),
};
export default config;Options
| Name | Type | Description |
|---|---|---|
config (param) | { [key: string]: string } | Existing environment variables (from .env files or shell) |
| return value | { [key: string]: string } | Merged object of existing and new variables |
Notes
- Always spread the incoming
configto preserve pre-existing variables - Variables defined here are accessible in story files and preview
features
Enables or disables Storybook's built-in capabilities and experimental functionalities.
Type
{
actions?: boolean;
argTypeTargetsV7?: boolean;
backgrounds?: boolean;
changeDetection?: boolean;
componentsManifest?: boolean;
controls?: boolean;
developmentModeForBuild?: boolean;
experimentalCodeExamples?: boolean;
experimentalTestSyntax?: boolean;
highlight?: boolean;
interactions?: boolean;
legacyDecoratorFileOrder?: boolean;
measure?: boolean;
outline?: boolean;
sidebarOnboardingChecklist?: boolean;
toolbars?: boolean;
viewport?: boolean;
}Usage
// .storybook/main.ts
import type { StorybookConfig } from '@storybook/your-framework';
const config: StorybookConfig = {
framework: '@storybook/your-framework',
stories: ['../src/**/*.stories.@(js|jsx|ts|tsx)'],
features: {
experimentalCodeExamples: true,
experimentalTestSyntax: true,
componentsManifest: false,
},
};
export default config;Options
| Name | Type | Default | Description |
|---|---|---|---|
actions | boolean | true | Enables the Actions addon |
backgrounds | boolean | true | Enables the Backgrounds feature |
changeDetection | boolean | true | Monitors git working tree and builder's module graph to show new/modified/related stories |
controls | boolean | true | Enables the Controls addon |
highlight | boolean | true | Enables element highlight inspection |
interactions | boolean | true | Enables interaction test debugging tools |
measure | boolean | true | Enables the Measure tool |
outline | boolean | true | Enables visual element outline |
viewport | boolean | true | Enables the Viewport addon |
componentsManifest | boolean | false | Generates manifests for MCP server integration |
sidebarOnboardingChecklist | boolean | true | Shows the onboarding checklist in sidebar |
argTypeTargetsV7 | boolean | true | (Experimental) Filters args with "target" properties from render functions |
developmentModeForBuild | boolean | — | Sets NODE_ENV to development in built Storybooks |
experimentalCodeExamples | boolean | — | (Experimental) Faster, more accurate code generation for autodocs |
experimentalTestSyntax | boolean | — | (Experimental) Enables CSF Next .test method syntax |
legacyDecoratorFileOrder | boolean | — | Applies preview.js decorators before addon/framework decorators |
Notes
- Most features default to
true; set tofalseonly when needed - Experimental features may change or be removed in future releases
experimentalCodeExamplesreads source files directly; dynamic control updates are not reflected
Related
- addons.md
- docs.md
framework
Required. Configures Storybook based on your UI framework, determining the rendering engine and build tooling.
Type
type FrameworkConfig = FrameworkName | {
name: FrameworkName;
options?: FrameworkOptions;
}
// FrameworkName: string (e.g. '@storybook/react-vite', '@storybook/nextjs')
// FrameworkOptions: Record<string, any>Usage
// .storybook/main.ts
import type { StorybookConfig } from '@storybook/your-framework';
const config: StorybookConfig = {
framework: {
name: '@storybook/your-framework',
options: {
legacyRootApi: true,
},
},
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
};
export default config;Options
| Name | Type | Description |
|---|---|---|
name | string | Framework package identifier (e.g. '@storybook/react-vite') |
options | Record<string, any> | Framework-specific configuration parameters |
options.builder | Record<string, any> | Configures the underlying build tool (Vite or Webpack) |
Notes
- This field is required in every
.storybook/main.ts - Available options vary significantly by framework; consult framework-specific docs
framework.options.builderis preferred over the legacycore.builder.options
Related
- core.md
- vite-final.md
- webpack-final.md
indexers
Customizes how Storybook discovers and parses story files, enabling custom story formats.
Type
// Config key is `experimental_indexers`
type experimental_indexers = (existingIndexers: Indexer[]) => Promise<Indexer[]>
type Indexer = {
test: RegExp;
createIndex: (fileName: string, options: IndexerOptions) => Promise<IndexInput[]>;
}
type IndexerOptions = {
makeTitle: (userTitle?: string) => string;
}
type IndexInput = {
exportName: string; // required
type: 'story'; // required
importPath?: string; // default: fileName
subtype?: 'story' | 'test'; // default: 'story'
rawComponentPath?: string;
metaId?: string;
name?: string;
tags?: string[];
title?: string;
__id?: string;
}Usage
// .storybook/main.ts
import type { StorybookConfig, Indexer } from '@storybook/your-framework';
const customIndexer: Indexer = {
test: /\.custom-stories\.[tj]sx?$/,
createIndex: async (fileName, { makeTitle }) => {
return [{
type: 'story',
title: makeTitle('MyComponent'),
importPath: fileName,
exportName: 'Default',
}];
},
};
const config: StorybookConfig = {
framework: '@storybook/your-framework',
stories: ['../src/**/*.stories.*', '../src/**/*.custom-stories.*'],
experimental_indexers: async (existingIndexers) => [
...existingIndexers,
customIndexer,
],
};
export default config;Notes
- Experimental: use the
experimental_indexerskey (notindexers) in config - Files matching your indexer's pattern must also be included in the
storiesarray - Always use
makeTitle()for consistent sidebar title formatting - Custom
importPathvalues are only supported in Vite; Webpack requires direct CSF transpilation - Custom source formats typically need builder-level transpilation (Vite/Webpack plugin) to convert to CSF
Related
- stories.md
logLevel
Controls the verbosity of Storybook's browser console logging.
Type
type logLevel = 'debug' | 'error' | 'info' | 'trace' | 'warn'Usage
// .storybook/main.ts
import type { StorybookConfig } from '@storybook/your-framework';
const config: StorybookConfig = {
framework: '@storybook/your-framework',
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
logLevel: 'debug',
};
export default config;Options
| Level | Description |
|---|---|
'trace' | Most verbose; trace-level diagnostics |
'debug' | Detailed debugging information |
'info' | Standard informational messages (default) |
'warn' | Warning and error messages |
'error' | Error messages only |
Notes
- Default value is
'info' - Applies to browser console logs, not the terminal/server logs
managerHead
Programmatically modifies the manager UI's <head> section.
Type
type managerHead = (head: string) => stringUsage
// .storybook/main.ts
import type { StorybookConfig } from '@storybook/your-framework';
const config: StorybookConfig = {
framework: '@storybook/your-framework',
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
managerHead: (head) => `
${head}
<link rel="preload" href="/fonts/my-custom-manager-font.woff2" />
`,
};
export default config;Notes
- For static additions (no runtime logic needed), use
manager-head.htmlinstead - Commonly used by addon authors who need conditional head injection
- The function receives existing head content and must return the complete modified string
Related
- preview-head.md
- preview-body.md
previewAnnotations
Adds scripts that execute within the story preview environment. Intended for framework maintainers.
Type
type previewAnnotations =
| string[]
| ((config: string[], options: Options) => string[] | Promise<string[]>)Usage
// Used in a framework preset (e.g. @storybook/nextjs)
import type { StorybookConfig } from './types';
export const previewAnnotations: StorybookConfig['previewAnnotations'] = (entry = []) => [
...entry,
import.meta.resolve('@storybook/nextjs/preview'),
];Notes
- Intended for framework developers, not typical Storybook users or addon authors
- Addon authors and end users should configure
preview.jsinstead - Supports both static string arrays and async function-based configuration
Related
- preview-head.md
- preview-body.md
previewBody
Programmatically modifies the preview iframe's <body> element.
Type
type previewBody = (body: string) => stringUsage
// .storybook/main.ts
import type { StorybookConfig } from '@storybook/your-framework';
const config: StorybookConfig = {
framework: '@storybook/your-framework',
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
previewBody: (body) => `
${body}
${
process.env.ANALYTICS_ID
? '<script src="https://cdn.example.com/analytics.js"></script>'
: ''
}
`,
};
export default config;Notes
- For static additions (no runtime logic needed), use
preview-body.htmlinstead - Commonly used by addon authors for conditional script/style injection
Related
- preview-head.md
- manager-head.md
previewHead
Programmatically modifies the preview iframe's <head> section.
Type
type previewHead = (head: string) => stringUsage
// .storybook/main.ts
import type { StorybookConfig } from '@storybook/your-framework';
const config: StorybookConfig = {
framework: '@storybook/your-framework',
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
previewHead: (head) => `
${head}
${
process.env.ANALYTICS_ID
? '<script src="https://cdn.example.com/analytics.js"></script>'
: ''
}
`,
};
export default config;Notes
- For static additions (no runtime logic needed), use
preview-head.htmlinstead - Commonly used by addon authors for conditional head injection
Related
- preview-body.md
- manager-head.md
Storybook API — main.js|ts Configuration
Configuration options for .storybook/main.js|ts. The file must be valid ESM and export a default config object typed as StorybookConfig.
import type { StorybookConfig } from '@storybook/your-framework';
const config: StorybookConfig = { /* options below */ };
export default config;| Name | Description | Path |
|---|---|---|
framework | Required. Specifies the UI framework and build tooling | ./framework.md |
stories | Required. Glob patterns or specifiers for story file discovery | ./stories.md |
addons | Registers addon packages | ./addons.md |
babel | Customizes Babel config (requires addon-webpack5-compiler-babel) | ./babel.md |
build | Optimizes production builds for testing scenarios | ./build.md |
core | Configures internal features: dev server, builder, telemetry | ./core.md |
docs | Controls auto-generated documentation pages | ./docs.md |
env | Defines custom environment variables | ./env.md |
features | Enables or disables built-in and experimental features | ./features.md |
experimental_indexers | Customizes story file discovery and parsing (experimental) | ./indexers.md |
logLevel | Sets browser console log verbosity | ./log-level.md |
managerHead | Programmatically injects content into the manager <head> | ./manager-head.md |
previewAnnotations | Adds scripts to the preview environment (for framework authors) | ./preview-annotations.md |
previewBody | Programmatically injects content into the preview <body> | ./preview-body.md |
previewHead | Programmatically injects content into the preview <head> | ./preview-head.md |
refs | Embeds external Storybook instances (composition) | ./refs.md |
staticDirs | Serves static asset directories to stories | ./static-dirs.md |
swc | Customizes SWC compiler config (requires addon-webpack5-compiler-swc) | ./swc.md |
tags | Defines custom tags and sidebar filter defaults | ./tags.md |
typescript | Manages TypeScript processing and React docgen | ./typescript.md |
viteFinal | Customizes Vite configuration (Vite builders only) | ./vite-final.md |
webpackFinal | Customizes Webpack configuration (Webpack builders only) | ./webpack-final.md |
refs
Configures Storybook composition by embedding external Storybook instances.
Type
type refs = {
[key: string]:
| { title: string; url: string; expanded?: boolean; sourceUrl?: string }
| ((config: { title: string; url: string; expanded?: boolean; sourceUrl?: string }) =>
{ title: string; url: string; expanded?: boolean; sourceUrl?: string })
| { disable: boolean }
}Usage
// .storybook/main.ts
import type { StorybookConfig } from '@storybook/your-framework';
const config: StorybookConfig = {
framework: '@storybook/your-framework',
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
refs: {
'design-system': {
title: 'Storybook Design System',
url: 'https://master--5ccbc373887ca40020446347.chromatic.com/',
expanded: false,
sourceUrl: 'https://github.com/storybookjs/storybook',
},
},
};
export default config;Options
| Name | Type | Default | Description |
|---|---|---|---|
title | string | — | Display name in the composed Storybook sidebar |
url | string | — | URL of the external Storybook instance |
expanded | boolean | true | Controls initial sidebar visibility |
sourceUrl | string | — | Link to associated source code repository |
disable | boolean | — | Set to true to prevent automatic composition of a package dependency |
Notes
- Package dependencies automatically compose their Storybooks by default
- Use a function for environment-specific URLs (development vs. production)
disable: trueprevents a specific package from being auto-composed
staticDirs
Configures directories containing static files that Storybook serves to stories.
Type
type staticDirs = (string | { from: string; to: string })[]Usage
// .storybook/main.ts
import type { StorybookConfig } from '@storybook/your-framework';
const config: StorybookConfig = {
framework: '@storybook/your-framework',
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
staticDirs: [
'../public',
{ from: '../my-custom-assets/images', to: '/assets' },
],
};
export default config;Options
| Name | Type | Description |
|---|---|---|
from | string | Source directory path relative to the config file |
to | string | Destination URL path in the served static directory |
Notes
- Simple string entries serve the directory at the root
- When using Vite-based frameworks, additional directories may be copied due to Vite's own static asset handling; disable by setting Vite's
publicDirtofalse
stories
Required. Determines which files Storybook loads as story definitions.
Type
type stories =
| (string | StoriesSpecifier)[]
| async (list: (string | StoriesSpecifier)[]) => (string | StoriesSpecifier)[]
type StoriesSpecifier = {
directory: string;
files?: string;
titlePrefix?: string;
}Usage
// .storybook/main.ts
import type { StorybookConfig } from '@storybook/your-framework';
const config: StorybookConfig = {
framework: '@storybook/your-framework',
stories: [
'../src/**/*.mdx',
'../src/**/*.stories.@(js|jsx|mjs|ts|tsx)',
],
};
export default config;Options
| Name | Type | Default | Description |
|---|---|---|---|
directory | string | — | Where to begin searching, relative to project root |
files | string | `'*/.@(mdx\ | stories.@(js\ |
titlePrefix | string | '' | Prefix for auto-generated story titles |
Notes
- This field is required in every
.storybook/main.ts - Stories appear in the sidebar in the order they are defined in the array
- Custom async implementations may reduce static analysis optimization
Related
- indexers.md
swc
Customizes Storybook's SWC compiler configuration for Webpack-based projects.
Type
type swc = (
config: swc.Options,
options: { configType?: 'DEVELOPMENT' | 'PRODUCTION' }
) => swc.Options | Promise<swc.Options>Usage
// .storybook/main.ts
import type { Options } from '@swc/core';
import type { StorybookConfig } from '@storybook/your-framework';
const config: StorybookConfig = {
framework: {
name: '@storybook/your-framework',
options: {},
},
swc: (config: Options, options): Options => {
return {
...config,
// Apply your custom SWC configuration
};
},
};
export default config;Options
| Name | Type | Description |
|---|---|---|
config (param) | swc.Options | Existing SWC configuration to modify |
options.configType | `'DEVELOPMENT' \ | 'PRODUCTION'` |
Notes
- Only applicable when
@storybook/addon-webpack5-compiler-swcaddon is enabled - Function can return a Promise for async configuration
- Refer to the SWC documentation for available options
Related
- babel.md
- webpack-final.md
tags
Defines custom tags for stories or modifies default behavior of built-in tags.
Type
type tags = {
[tagName: string]: {
defaultFilterSelection?: 'include' | 'exclude';
}
}Usage
// .storybook/main.ts
import type { StorybookConfig } from '@storybook/your-framework';
const config: StorybookConfig = {
framework: '@storybook/your-framework',
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
tags: {
experimental: {
defaultFilterSelection: 'exclude',
},
},
};
export default config;Options
| Name | Type | Description |
|---|---|---|
[tagName] | string | Tag name (built-in or custom); must be a static string |
defaultFilterSelection | `'include' \ | 'exclude'` |
Notes
- Tags are used for filtering stories in the Storybook sidebar
- This configuration applies globally across the entire Storybook instance
- When
defaultFilterSelectionis omitted, the tag has no default selection behavior
typescript
Manages how Storybook processes TypeScript files, including type checking and React component documentation.
Type
{
check?: boolean;
checkOptions?: CheckOptions;
reactDocgen?: 'react-docgen' | 'react-docgen-typescript' | false;
reactDocgenTypescriptOptions?: ReactDocgenTypescriptOptions;
skipCompiler?: boolean;
}Usage
// .storybook/main.ts
import type { StorybookConfig } from '@storybook/your-framework';
const config: StorybookConfig = {
framework: '@storybook/your-framework',
typescript: {
reactDocgen: 'react-docgen-typescript',
reactDocgenTypescriptOptions: {
shouldExtractLiteralValuesFromEnum: true,
propFilter: (prop) =>
prop.parent ? !/node_modules/.test(prop.parent.fileName) : true,
},
},
};
export default config;Options
| Name | Type | Default | Description |
|---|---|---|---|
check | boolean | — | Runs fork-ts-checker-webpack-plugin (Webpack only) |
checkOptions | CheckOptions | — | Options passed to fork-ts-checker-webpack-plugin |
reactDocgen | `'react-docgen' \ | 'react-docgen-typescript' \ | false` |
reactDocgenTypescriptOptions | ReactDocgenTypescriptOptions | — | Options passed to the react-docgen-typescript-plugin |
skipCompiler | boolean | — | Disables TypeScript compiler processing for Webpack5 builds |
Notes
checkis Webpack-specific and unavailable for Vite buildsreact-docgenis faster but may miss complex types;react-docgen-typescriptis slower but more accurate- The default
propFilterexcludes node_modules from documentation extraction
Related
- docs.md
- babel.md
viteFinal
Customizes Storybook's Vite configuration when using a Vite-based builder.
Type
type viteFinal = (
config: Vite.InlineConfig,
options: { configType?: 'DEVELOPMENT' | 'PRODUCTION' }
) => Vite.InlineConfig | Promise<Vite.InlineConfig>Usage
// .storybook/main.ts
import type { StorybookConfig } from '@storybook/your-framework';
const config: StorybookConfig = {
framework: '@storybook/your-framework',
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
async viteFinal(config, { configType }) {
const { mergeConfig } = await import('vite');
if (configType === 'DEVELOPMENT') {
// development-only modifications
}
if (configType === 'PRODUCTION') {
// production-only modifications
}
return mergeConfig(config, {
// your custom Vite options
});
},
};
export default config;Options
| Name | Type | Description |
|---|---|---|
config (param) | Vite.InlineConfig | Storybook's prepared Vite configuration |
options.configType | `'DEVELOPMENT' \ | 'PRODUCTION'` |
Notes
- Use Vite's
mergeConfigutility to safely merge custom settings - The function can be
asyncfor dynamic configuration loading - Only applicable when using a Vite-based framework
Related
- webpack-final.md
- framework.md
- core.md
webpackFinal
Customizes Storybook's Webpack configuration when using a Webpack-based builder.
Type
type webpackFinal = (
config: Config,
options: { configType?: 'DEVELOPMENT' | 'PRODUCTION' }
) => Config | Promise<Config>Usage
// .storybook/main.ts
import type { StorybookConfig } from '@storybook/your-framework';
const config: StorybookConfig = {
framework: '@storybook/your-framework',
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
webpackFinal: async (config, { configType }) => {
if (configType === 'DEVELOPMENT') {
// development-only modifications
}
if (configType === 'PRODUCTION') {
// production-only modifications
}
return config;
},
};
export default config;Options
| Name | Type | Description |
|---|---|---|
config (param) | Config | Storybook's prepared Webpack configuration |
options.configType | `'DEVELOPMENT' \ | 'PRODUCTION'` |
Notes
- Only applicable when using a Webpack-based builder
- Must return the modified Webpack configuration object
- Function must be
async
Related
- vite-final.md
- framework.md
- babel.md
- swc.md
Frameworks (Adding New Framework Support)
How to create a new framework integration for Storybook.
Overview
Storybook supports React, Vue, Angular, Web Components, Svelte, and others. To add a new framework you need to provide: (1) server-side build configuration and (2) client-side rendering logic.
Use @storybook/html as a starting point — it has no framework-specific peculiarities and an available boilerplate template.
Project Structure
app/<framework>/ # framework package
examples/<framework>-kitchen-sink/ # example applicationServer-Side Setup
package.json bin entries
{
"bin": {
"storybook": "./bin/index.js",
"build-storybook": "./bin/build.js"
}
}Both scripts pass an options object to @storybook/core/server.
Server Options
export default {
packageJson: JSON.parse(readFileSync(pkg.up({ cwd: process.cwd() }))),
framework: 'vue',
frameworkPresets: [import.meta.resolve('./framework-preset-vue.js')],
// optional: frameworkPath resolves from .storybook dir to dist/client/index.js
};| Option | Description |
|---|---|
framework | String identifier passed to addons for framework-specific tasks |
frameworkPresets | Array of preset paths with webpack/babel customizations |
frameworkPath | Optional path to custom client entry (dist/client/index.js) |
Client-Side Implementation
Renderable Objects
Stories return framework-specific objects:
// Vue-style story
export const Sample: Story = {
render: () => ({
template: '<button :label="label" />',
data: { label: 'hello button' },
}),
};Render Function
const rootElement = document.getElementById('root');
export default function renderMain({ storyFn }: RenderMainArgs) {
const storyObj = storyFn();
const html = fn(storyObj);
rootElement.innerHTML = html;
}Client Entry (src/client/preview/index.ts)
import { start } from 'storybook/preview-api';
import './globals';
import render from './render';
const api = start(render);Globals File
import { global } from '@storybook/global';
global.window.STORYBOOK_ENV = 'vue';Reference Implementations
| Framework | Location |
|---|---|
| React | code/renderers/react |
| Vue 3 | code/renderers/vue3 |
| Angular | code/frameworks/angular |
| Web Components | code/renderers/web-components |
Notes
- Framework presets are standard Storybook presets — use them for webpack/babel customization
- The server options object abstracts framework-independent functionality via
@storybook/core/server frameworkPathshould resolve todist/client/index.jswithin your framework package
Related
- CLI Options
- CSF
Parameters
Static metadata used to configure stories and addons in Storybook.
Overview
Parameters are plain objects attached at three levels — story, component (meta), or project (.storybook/preview.ts). They merge hierarchically: project → meta → story, with objects deep-merged and primitives/arrays overwritten at each level.
Usage
// Project level — .storybook/preview.ts
export const parameters = {
layout: 'centered',
backgrounds: {
default: 'light',
values: [
{ name: 'light', value: '#fff' },
{ name: 'dark', value: '#333' },
],
},
};
// Component level
const meta = {
component: Button,
parameters: { layout: 'padded' },
} satisfies Meta<typeof Button>;
// Story level
export const FullPage: Story = {
parameters: { layout: 'fullscreen' },
};Core Parameters
layout
| Value | Description |
|---|---|
'padded' | Default — adds padding around the story |
'centered' | Centers the story horizontally and vertically |
'fullscreen' | No padding, fills the canvas |
options (project-level only)
Controls story ordering via storySort.
// preview.ts
export const parameters = {
options: {
storySort: {
method: 'alphabetical', // 'alphabetical' | 'configure'
order: ['Intro', 'Components'], // explicit ordering array
locales: 'en-US',
includeNames: true,
},
},
};storySort also accepts a comparator function (a, b) => number.
test
Controls mock behavior between stories (useful with Vitest).
| Option | Type | Default | Description |
|---|---|---|---|
clearMocks | boolean | false | Clear mock call history on unmount |
mockReset | boolean | false | Reset mocks to empty functions on unmount |
restoreMocks | boolean | true | Restore original implementations on unmount |
dangerouslyIgnoreUnhandledErrors | boolean | false | Suppress unhandled errors from causing test failure |
Essential Addon Parameters
The following parameters are provided by built-in addons:
| Parameter | Addon | Description |
|---|---|---|
actions | @storybook/addon-actions | Event handler tracking config |
backgrounds | @storybook/addon-backgrounds | Canvas background options |
controls | @storybook/addon-controls | Controls panel configuration |
docs | @storybook/addon-docs | Documentation generation settings |
highlight | @storybook/addon-highlight | Element highlighting |
viewport | @storybook/addon-viewport | Responsive device simulation |
a11y | @storybook/addon-a11y | Accessibility check config |
Notes
- Objects deep-merge across levels; arrays and primitives are overwritten (more specific level wins)
parametersat story level always takes highest precedence
Related
- CSF
- ArgTypes
Portable Stories — Jest
API for reusing Storybook stories in Jest tests.
Overview
Import from @storybook/your-framework. Available since Storybook 8.2.7.
CSF Factories format eliminates the need for this API — prefer that when available.
setProjectAnnotations()
Apply project-level annotations once before all tests. Call this in your Jest setup file.
Signature
setProjectAnnotations(
projectAnnotations: ProjectAnnotation | ProjectAnnotation[]
) => ProjectAnnotationUsage
// jest.setup.ts (configured in jest.config.js setupFilesAfterFramework)
import { setProjectAnnotations } from '@storybook/your-framework';
import * as previewAnnotations from './.storybook/preview';
setProjectAnnotations([previewAnnotations]);---
composeStories()
Process all stories from a CSF file into renderable, composed components.
Signature
composeStories(
csfExports: CSF file exports,
projectAnnotations?: ProjectAnnotation | ProjectAnnotation[]
) => Record<string, ComposedStoryFn>Parameters
| Parameter | Required | Description |
|---|---|---|
csfExports | Yes | Full import * as stories from './Button.stories' |
projectAnnotations | No | Override project-level annotations |
Return Value
Object of composed story functions. Each exposes:
args,argTypes,id,parameters,storyName,tags.play()— execute play function only.run()— mount component + execute play function
Usage
import { render, screen } from '@testing-library/react';
import { composeStories } from '@storybook/react';
import * as stories from './Button.stories';
const { Primary } = composeStories(stories);
test('renders primary button', () => {
render(<Primary />);
expect(screen.getByText('Text coming from args')).toBeTruthy();
});---
composeStory()
Compose a single story for targeted testing.
Signature
composeStory(
story: Story export,
componentAnnotations: Meta,
projectAnnotations?: ProjectAnnotation | ProjectAnnotation[],
exportsName?: string
) => ComposedStoryFnParameters
| Parameter | Required | Description |
|---|---|---|
story | Yes | Individual named story export |
componentAnnotations | Yes | Default export (Meta) from stories file |
projectAnnotations | No | Override project annotations |
exportsName | No | Story export name for unique identification |
Usage
import { composeStory } from '@storybook/react';
import meta, { Primary as PrimaryStory } from './Button.stories';
const Primary = composeStory(PrimaryStory, meta);
test('renders with override', async () => {
await Primary.run({ args: { onClick: jest.fn() } });
});Notes
- Requires Storybook 8.2.7+
- For Next.js: import from
@storybook/nextjsand usenext/jest.jstransformer - Assertions inside play functions cause the test to fail
- Composed stories accept prop overrides merged with story args
Related
- Portable Stories — Vitest
- Portable Stories — Playwright
- CSF
Portable Stories — Playwright
API for reusing Storybook stories in Playwright Component Tests (CT).
Overview
Import from @storybook/react/experimental-playwright. This API is experimental, requires React 18+, and is not yet supported with Next.js.
Stories must be composed in a separate `.portable.ts` file because Playwright transforms code between Node and browser contexts.
setProjectAnnotations()
Apply project-level annotations before tests run. Call this in your playwright/index.ts setup file.
Signature
setProjectAnnotations(
projectAnnotations: ProjectAnnotation | ProjectAnnotation[]
) => ProjectAnnotationUsage
// playwright/index.ts
import { setProjectAnnotations } from '@storybook/react';
import * as previewAnnotations from './.storybook/preview';
import * as addonAnnotations from 'my-addon/preview';
const annotations = setProjectAnnotations([previewAnnotations, addonAnnotations]);
test.beforeAll(annotations.beforeAll);---
createTest(baseTest)
Extend Playwright's test with a Storybook-aware mount that runs the full story pipeline.
Signature
createTest(baseTest: PlaywrightFixture) => PlaywrightFixtureParameters
| Parameter | Required | Description |
|---|---|---|
baseTest | Yes | Base test from @playwright/experimental-ct-react |
Return Value
A Playwright test fixture with an enhanced mount that automatically: 1. Applies annotations 2. Runs loaders 3. Renders the story 4. Executes the play function (including assertions)
Usage
import { createTest } from '@storybook/react/experimental-playwright';
import { test as base } from '@playwright/experimental-ct-react';
import stories from './Button.stories.portable';
const test = createTest(base);
test('renders primary', async ({ mount }) => {
await mount(<stories.Primary />);
});
test('renders with props', async ({ mount }) => {
const component = await mount(<stories.Primary label="Custom" />);
await expect(component).toContainText('Custom');
});---
Story Composition Pattern
Create a .portable.ts file alongside your stories:
// Button.stories.portable.ts
import { composeStories } from '@storybook/react';
import * as stories from './Button.stories';
export default composeStories(stories);Then import in your test file:
import stories from './Button.stories.portable';Overriding Globals
// Button.stories.portable.ts
import { composeStory } from '@storybook/react';
import meta, { Primary } from './Button.stories';
export const PrimaryEnglish = composeStory(Primary, meta, { globals: { locale: 'en' } });
export const PrimarySpanish = composeStory(Primary, meta, { globals: { locale: 'es' } });Notes
- API is experimental — subject to breaking changes
- Requires React 18+; Next.js is not supported
- If play function assertions fail, the test fails accordingly
- Addon decorators/loaders needed for rendering must be included via
setProjectAnnotations()
Related
- Portable Stories — Vitest
- Portable Stories — Jest
- CSF
Portable Stories
Reuse Storybook stories in external test environments by manually managing the story composition pipeline.
Overview
Storybook normally handles story composition automatically in the browser. Portable stories expose that pipeline so stories can run in Vitest, Jest, or Playwright Component Tests.
Story pipeline stages: 1. Apply project annotations — setProjectAnnotations() 2. Compose story — composeStories() or composeStory() 3. Run story — .run() method (mounts component + executes loaders and play function)
Note: Storybook recommends using the Vitest addon for automatic story transformation when possible.
Index
| Name | Description | Path |
|---|---|---|
Portable Stories — Vitest | API for using stories in Vitest tests | ./vitest.md |
Portable Stories — Jest | API for using stories in Jest tests | ./jest.md |
Portable Stories — Playwright | API for using stories in Playwright CT | ./playwright.md |
Related
- CSF
- ArgTypes
- Parameters
Portable Stories — Vitest
API for reusing Storybook stories in Vitest tests.
Overview
Import from @storybook/your-framework. Storybook recommends the Vitest addon for automatic transformation, but this API is available for direct usage.
setProjectAnnotations()
Apply project-level annotations once before all tests run.
Signature
setProjectAnnotations(
projectAnnotations: ProjectAnnotation | ProjectAnnotation[]
) => ProjectAnnotationUsage
// vitest.setup.ts
import { beforeAll } from 'vitest';
import { setProjectAnnotations } from '@storybook/your-framework';
import * as previewAnnotations from './.storybook/preview';
import * as addonAnnotations from 'my-addon/preview';
const annotations = setProjectAnnotations([previewAnnotations, addonAnnotations]);
beforeAll(annotations.beforeAll);---
composeStories()
Transform all stories from a CSF file into testable components with all annotations applied.
Signature
composeStories(
csfExports: CSF file exports,
projectAnnotations?: ProjectAnnotations
) => Record<string, ComposedStoryFn>Parameters
| Parameter | Required | Description |
|---|---|---|
csfExports | Yes | Full import * as stories from './Button.stories' |
projectAnnotations | No | Override project-level annotations |
Return Value
Object mapping story names to composed story functions. Each function exposes:
args,argTypes,id,parameters,storyName,tags.play()— execute play function only.run()— mount component and execute full lifecycle
Usage
import { composeStories } from '@storybook/your-framework';
import * as stories from './Button.stories';
const { Primary, Secondary } = composeStories(stories);
test('renders primary', async () => {
await Primary.run();
});
test('renders with override', async () => {
await Primary.run({ args: { ...Primary.args, children: 'Hello' } });
});---
composeStory()
Compose a single story for targeted testing.
Signature
composeStory(
story: Story export,
componentAnnotations: Meta,
projectAnnotations?: ProjectAnnotations,
exportsName?: string
) => ComposedStoryFnParameters
| Parameter | Required | Description |
|---|---|---|
story | Yes | Individual named story export |
componentAnnotations | Yes | Default export (Meta) from stories file |
projectAnnotations | No | Override project annotations |
exportsName | No | Story export name for unique identification |
Usage
import { composeStory } from '@storybook/your-framework';
import meta, { Primary as PrimaryStory } from './Button.stories';
const Primary = composeStory(PrimaryStory, meta);
test('renders primary', async () => {
await Primary.run();
});Notes
- Include addon
previewexports insetProjectAnnotations()if stories rely on addon decorators/loaders - Assertions inside play functions cause the test to fail when they fail
- Override globals per-test:
composeStory(story, meta, { globals: { locale: 'en' } }) - For Next.js, install
@storybook/nextjs-vitefor proper Vitest integration
Related
- Portable Stories — Jest
- Portable Stories — Playwright
- CSF
API
| Name | Description | Path |
|---|---|---|
| ArgTypes | Specify arg behavior, constrain acceptable values, and configure the Controls panel and documentation. | arg-types.md |
| CLI Options | All Storybook CLI commands and their available flags. | cli-options.md |
| CSF — Component Story Format | An open standard for writing Storybook stories based on ES6 modules, portable beyond Storybook itself. | csf.md |
| Frameworks (Adding New Framework Support) | How to create a new framework integration for Storybook. | new-frameworks.md |
| Parameters | Static metadata used to configure stories and addons in Storybook. | parameters.md |
Builder API
Interface for implementing custom Storybook builders that compile components and stories into browser-runnable JavaScript bundles.
Overview
The Builder API allows developers to create custom builders for Storybook. A builder is responsible for starting a development server with HMR support and producing static production builds. This area is under rapid development; open an RFC with the Storybook community before implementing a custom builder.
Signature / Usage
All builders must implement the following TypeScript interface:
export interface Builder<Config, BuilderStats extends Stats = Stats> {
getConfig: (options: Options) => Promise<Config>;
start: (args: {
options: Options;
startTime: ReturnType<typeof process.hrtime>;
router: ServerApp;
server: HttpServer;
channel: ServerChannel;
}) => Promise<void | {
stats?: BuilderStats;
totalTime: ReturnType<typeof process.hrtime>;
bail: (e?: Error) => Promise<void>;
}>;
build: (arg: {
options: Options;
startTime: ReturnType<typeof process.hrtime>;
}) => Promise<void | BuilderStats>;
bail: (e?: Error) => Promise<void>;
corePresets?: string[];
overridePresets?: string[];
}Options / Props
| Method | Description |
|---|---|
getConfig | Retrieves the builder's resolved configuration options |
start | Initializes the development server with file watching and HMR |
build | Generates a static production build |
bail | Gracefully terminates the development server |
corePresets | Optional list of core preset paths |
overridePresets | Optional list of preset overrides |
Configuration
Specify a builder in .storybook/main.ts:
const config: StorybookConfig = {
framework: '@storybook/your-framework',
core: {
builder: '@storybook/builder-vite', // or any custom builder
},
};Notes
- Builders must handle story loading via glob patterns from the
storiesconfig field. - MDX support,
preview.jsexports conversion, source code snippet generation, and HMR are all required capabilities. - Reference implementations: Vite builder, Webpack 5 builder (
code/builders/builder-webpack5), and Modern Web'sdev-server-storybook. - This API is under active development — consult the Storybook community via RFC before building a custom builder.
Related
- Vite Builder
- Webpack Builder
builders
| Name | Description | Path |
|---|---|---|
| Builder API | Interface for implementing custom Storybook builders that compile components and stories into browser-runnable JavaScript bundles. | builder-api.md |
| Vite Builder | Bundles Storybook components and stories using Vite, offering faster startup and hot module replacement compared to Webpack. | vite.md |
| Webpack Builder | Storybook's default bundler using Webpack 5, with zero-config support and extensive customization options. | webpack.md |
Vite Builder
Bundles Storybook components and stories using Vite, offering faster startup and hot module replacement compared to Webpack.
Overview
The Vite builder (@storybook/builder-vite) is a fast ESM-based bundler ideal for Vite-based applications. It automatically merges your existing vite.config.js|ts and supports most frameworks out-of-the-box. Startup and refresh times are significantly faster than Webpack, though the execution environment differs.
Configuration
Installation
npm install @storybook/builder-vite --save-devBasic setup in .storybook/main.ts
import type { StorybookConfig } from '@storybook/your-framework';
const config: StorybookConfig = {
framework: '@storybook/your-framework',
stories: ['../src/**/*.mdx', '../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
core: {
builder: '@storybook/builder-vite',
},
};
export default config;Customizing with viteFinal
async viteFinal(config) {
const { mergeConfig } = await import('vite');
return mergeConfig(config, {
optimizeDeps: {
include: ['storybook-dark-mode'],
},
});
}Environment-based configuration
async viteFinal(config, { configType }) {
if (configType === 'DEVELOPMENT') {
// Development-specific options
}
if (configType === 'PRODUCTION') {
// Production-specific options
}
return mergeConfig(config, { /* config */ });
}Custom Vite config path
core: {
builder: {
name: '@storybook/builder-vite',
options: {
viteConfigPath: '../customVite.config.js',
},
},
}Notes
- Auto ArgType inference is limited to React, Vue 3, and Svelte (JSDocs only). React defaults to
react-docgen; revert withtypescript: { reactDocgen: 'react-docgen-typescript' }. - If interaction tests throw
window is undefined, add<script>window.global = window;</script>to.storybook/preview-head.html. - When migrating from Webpack, start with minimal Vite config — most features work automatically.
- Set
viteConfigPathto a non-existent file to prevent automatic Vite config loading.
Related
- Webpack Builder
- Builder API
Webpack Builder
Storybook's default bundler using Webpack 5, with zero-config support and extensive customization options.
Overview
The Webpack builder leverages your existing Webpack configuration while providing zero-config support for common use cases. It is the default builder when no alternative is specified during storybook init.
Configuration
Builder options in .storybook/main.ts
| Option | Type | Description |
|---|---|---|
fsCache | boolean | Enables Webpack filesystem caching |
lazyCompilation | boolean | Enables Webpack's experimental lazy compilation |
core: {
builder: {
name: '@storybook/builder-webpack5',
options: {
fsCache: true,
lazyCompilation: true,
},
},
}Extending with webpackFinal
webpackFinal: async (config, { configType }) => {
if (configType === 'DEVELOPMENT') {
// Development-specific changes
}
return config;
}Adding plugins
webpackFinal: async (config) => {
config.plugins.push(/* new plugin */);
return config;
}TypeScript path alias resolution
import TsconfigPathsPlugin from 'tsconfig-paths-webpack-plugin';
webpackFinal: async (config) => {
if (config.resolve) {
config.resolve.plugins = [
...(config.resolve.plugins || []),
new TsconfigPathsPlugin({
extensions: config.resolve.extensions,
}),
];
}
return config;
}Compiler Support
SWC (recommended for performance)
npx storybook@latest add @storybook/addon-webpack5-compiler-swcBabel
npx storybook@latest add @storybook/addon-webpack5-compiler-babelNotes
- Always preserve the
entryandoutputproperties when merging Webpack config inwebpackFinal. - Append to
config.pluginsrather than overwriting — Storybook relies onHtmlWebpackPlugin. - Debug the effective Webpack config with
npm run storybook -- --debug-webpack. - Webpack 4 is no longer supported; upgrade to Webpack 5.
- Storybook now uses esbuild for the manager UI — remove any
managerWebpackconfiguration.
Related
- Vite Builder
- Builder API
Addons
Extend and customize Storybook through the addon ecosystem.
Overview
Addons are tools that customize Storybook to match team workflows. Many core features, including documentation, are implemented as addons. They integrate via the toolbar, the addons panel, decorators, or build configuration.
Configuration
Install an Addon
// .storybook/main.ts
import type { StorybookConfig } from '@storybook/your-framework';
const config: StorybookConfig = {
addons: [
'@storybook/addon-docs',
'@storybook/addon-themes',
'@storybook/addon-a11y',
// addon with options
{
name: '@storybook/addon-styling-webpack',
options: {
// addon-specific options
},
},
],
};
export default config;Addon Categories
| Category | Description | Example |
|---|---|---|
| Core addons | Maintained by Storybook team; serve as reference implementations | @storybook/addon-docs |
| Community addons | Contributed by the wider developer community | Various npm packages |
Where Addons Appear
| Location | Description |
|---|---|
| Toolbar | Top of the Storybook interface |
| Addons panel | Bottom or right sidebar |
| Preview (decorators) | Wraps story rendering |
| Build config | Modifies webpack/Vite configuration |
Preset Addons
Some addons function as "presets" that provide pure infrastructure enhancements (e.g., configuring loaders, babel plugins) without adding UI elements.
Notes
- Addons are listed in the
addonsarray in.storybook/main.ts - Discover addons at the official Storybook addon catalog on storybook.js.org
- Core addons demonstrate idiomatic addon development patterns
Related
- Features and Behavior
- Theming
- Styling and CSS
Compilers
Note: This page has moved to /docs/configure/integration/compilers in the current documentation.Storybook integrates with SWC and Babel for JavaScript compilation and bundling.
Overview
Two major compilers are supported. SWC is the recommended default for Webpack-based projects due to its performance. Babel remains available for projects requiring its extensive plugin ecosystem.
SWC (Recommended)
SWC is a Rust-powered compiler that automatically becomes the default for Webpack-based projects (excluding Angular, Create React App, Ember.js, and Next.js).
Configuration
// .storybook/main.ts
import type { StorybookConfig } from '@storybook/your-framework';
const config: StorybookConfig = {
swc: (config, options) => ({
jsc: {
transform: {
react: {
runtime: 'automatic',
},
},
},
}),
};
export default config;Babel
Babel offers a modular architecture and extensive plugin system for broad compatibility.
Configuration Methods
- Project-wide:
babel.config.jsin the project root - File-relative:
.babelrc.jsonfor granular per-directory control
Notes
- SWC with React: if React imports are missing, configure
runtime: 'automatic'in.storybook/main.tsas shown above - Babel debugging: use the
BABEL_SHOW_CONFIG_FORenvironment variable to inspect config without blocking the build
Related
- Frameworks
- TypeScript
Environment Variables
Manage application behavior across environments using environment variables in Storybook.
Overview
Variables prefixed with STORYBOOK_ are automatically available throughout preview code. Variables can be set via the command line, .env files, or defined directly in main.ts.
Configuration
Command Line
STORYBOOK_THEME=red STORYBOOK_DATA_KEY=12345 npm run storybook.env Files
Create a .env file in your project root:
STORYBOOK_API_URL=https://api.example.com
STORYBOOK_FEATURE_FLAG=trueUse .env.development or .env.production for environment-specific values.
Define in main.ts
// .storybook/main.ts
import type { StorybookConfig } from '@storybook/your-framework';
const config: StorybookConfig = {
env: (config) => ({
...config,
EXAMPLE_VAR: 'An environment variable configured in Storybook',
}),
};
export default config;Accessing Variables in Stories
| Builder | Syntax |
|---|---|
| Webpack | process.env.STORYBOOK_THEME |
| Vite | import.meta.env.STORYBOOK_DATA_KEY |
// In a story or preview file
const theme = process.env.STORYBOOK_THEME; // Webpack
const theme = import.meta.env.STORYBOOK_THEME; // ViteBrowser Selection
Control which browser opens during storybook dev:
BROWSER="firefox" npm run storybook
# Options: safari, firefox, chromium
# Default: ChromeNotes
- Do not store secrets (private API keys, tokens) in Storybook environment variables; they are embedded into the build
- Only variables prefixed with
STORYBOOK_are exposed to preview code automatically - Framework-specific variables (e.g.,
VUE_APP_) may require additional framework configuration to be recognized
Related
- Story Rendering
- Features and Behavior
Features and Behavior
Note: This page has moved to /docs/configure/user-interface/features-and-behavior in the current documentation.Configure Storybook's UI layout and behavioral features via the addons.setConfig() API.
Overview
UI layout and feature flags are configured in .storybook/manager.js|ts using addons.setConfig(). This controls panel sizes, toolbar visibility, keyboard shortcuts, and more.
Configuration
// .storybook/manager.js
import { addons } from 'storybook/manager-api';
addons.setConfig({
navSize: 300,
bottomPanelHeight: 300,
rightPanelWidth: 300,
panelPosition: 'bottom',
enableShortcuts: true,
showToolbar: true,
selectedPanel: 'storybook/actions/panel',
initialActive: 'sidebar',
sidebar: {
showRoots: true,
collapsedRoots: ['other'],
renderLabel: (item) => <span>{item.name}</span>,
},
toolbar: {
title: { hidden: false },
zoom: { hidden: false },
eject: { hidden: false },
copy: { hidden: false },
fullscreen: { hidden: false },
},
});Layout Properties
| Property | Type | Description |
|---|---|---|
navSize | number (px) | Width of the sidebar showing story list |
bottomPanelHeight | number (px) | Height of the addon panel in bottom position |
rightPanelWidth | number (px) | Width of the addon panel in right position |
panelPosition | 'bottom' \ | 'right' |
enableShortcuts | boolean | Enable/disable keyboard shortcuts |
showToolbar | boolean | Toggle toolbar visibility |
theme | object | Custom Storybook theme |
selectedPanel | string | Default active addon panel ID |
initialActive | 'sidebar' \ | 'canvas' \ |
Dynamic Layout via Functions
addons.setConfig({
showSidebar: ({ viewMode }) => viewMode !== 'story',
showPanel: ({ storyTags }) => !storyTags.includes('no-panel'),
showToolbar: ({ viewMode }) => viewMode !== 'docs',
});URL Parameters
| Parameter | Values | Description |
|---|---|---|
shortcuts | false | Disable keyboard shortcuts |
full | `true\ | false` |
nav | `true\ | false` |
panel | `false\ | 'right'\ |
tabs | true | Enable tabs display |
Notes
- If hiding the sidebar via
showSidebar, ensure the displayed page provides an alternative means of navigation - Misusing layout customization functions can make Storybook navigation impossible
Related
- Theming
- Sidebar and URLs
- Story Layout
Frameworks
Note: This page has moved to /docs/configure/integration/frameworks in the current documentation.Storybook framework packages automatically configure Storybook for popular development environments.
Overview
When you install Storybook into an existing project, it detects your framework and automatically configures Storybook to work with it by adding necessary dependencies and adjusting configuration settings.
Supported Frameworks
| Builder | Frameworks |
|---|---|
| Webpack | React, Angular, Vue 3, Web Components, Next.js, HTML, Ember, Preact, Svelte |
| Vite | React, Vue 3, Web Components, HTML, Svelte, SvelteKit, Qwik, Solid |
Configuration
// .storybook/main.ts
import type { StorybookConfig } from '@storybook/your-framework';
const config: StorybookConfig = {
framework: {
name: '@storybook/your-framework',
options: {
// Framework-specific options
},
},
};
export default config;Framework-specific Options
| Framework | Option | Description |
|---|---|---|
| Next.js | nextConfigPath | Path to the Next.js config file |
| React | strictMode | Enable React strict mode |
| React | legacyRootApi | Use React 18 legacy root API |
| Angular | enableIvy | Enable Ivy (default in Angular 9+) |
| Angular | enableNgcc | Enable ngcc for backwards compatibility |
Notes
- Storybook maintains the same level of feature support across all frameworks
- Next.js 13+ support for TurboPack and Server Components is incomplete
- Legacy frameworks (Aurelia, Marionette, Mithril, Rax, Riot) are being deprecated
- Projects using custom configurations like CRACO may require additional addon or integration setup
Related
- Compilers
- TypeScript
Images and Assets
Note: This page has moved to /docs/configure/integration/images-and-assets in the current documentation.Three approaches for loading images, fonts, and other static assets in Storybook stories.
Overview
Components often require images, videos, fonts, and other assets. Storybook supports direct imports, static directory serving, and CDN references.
Configuration
1. Import Assets Directly
import imageFile from './static/image.png';
export const WithAnImage: Story = {
render: () => <img src={imageFile} alt="my image" />,
};Works automatically with Storybook's default configuration. Custom webpack setups may require the file loader.
2. Serve Static Files via staticDirs
// .storybook/main.ts
const config: StorybookConfig = {
staticDirs: ['../public', '../static'],
};Reference files with root-relative paths in stories:
export const WithAnImage: Story = {
render: () => <img src="/image.png" alt="my image" />,
};Map directories to custom URL paths:
staticDirs: [{ from: '../my-custom-assets/images', to: '/assets' }],3. Reference Assets from CDN
<img src="https://example.com/images/placeholder.png" alt="CDN asset" />Configuring Fonts
<!-- .storybook/preview-head.html -->
<link rel="preload" href="/fonts/my-font.woff2" />
<!-- External font service -->
<script src="https://use.typekit.net/xxxyyy.js"></script>
<script>
try { Typekit.load(); } catch (e) {}
</script>Notes
- When deploying Storybook to a subpath, use relative paths for static assets; imported assets handle this automatically
- Static directory assets require relative path syntax or the
<base>element for subpath deployments - Vite users: set
publicDir: falseinvite.config.jsif additional directory copying causes issues
Related
- Story Rendering
- Styling and CSS
Configure
| Name | Description | Path |
|---|---|---|
| Addons | Extend and customize Storybook through the addon ecosystem. | addons.md |
| Compilers | Storybook integrates with SWC and Babel for JavaScript compilation and bundling. | compilers.md |
| Environment Variables | Manage application behavior across environments using environment variables in Storybook. | environment-variables.md |
| Features and Behavior | Configure Storybook's UI layout and behavioral features via the addons.setConfig() API. | features-and-behavior.md |
| Frameworks | Storybook framework packages automatically configure Storybook for popular development environments. | frameworks.md |
| Images and Assets | Three approaches for loading images, fonts, and other static assets in Storybook stories. | images-and-assets.md |
| Sidebar and URLs | Organize Storybook's sidebar hierarchy and manage story permalinks. | sidebar-and-urls.md |
| Story Layout | Control how stories are positioned within Storybook's Canvas tab using the layout parameter. | story-layout.md |
| Story Rendering | Control how stories are rendered in Storybook's preview iframe (Canvas). | story-rendering.md |
| Styling and CSS | Configure CSS and styling in Storybook to match your application's styling approach. | styling-and-css.md |
| Telemetry | Configure Storybook's anonymous usage data collection. | telemetry.md |
| Theming | Customize Storybook's UI appearance using the built-in theming API. | theming.md |
| TypeScript | Storybook provides zero-configuration TypeScript support with type-safe story authoring. | typescript.md |
Sidebar and URLs
Note: This page has moved to /docs/configure/user-interface/sidebar-and-urls in the current documentation.Organize Storybook's sidebar hierarchy and manage story permalinks.
Overview
The sidebar organizes stories hierarchically using forward slashes (/) in story titles. Story IDs are derived from titles and used in URLs; they can be manually set to preserve permalinks when renaming.
Configuration
Sidebar Roots
By default, top-level nodes appear as "sections" (roots). To display them as folders instead:
// .storybook/manager.js
import { addons } from 'storybook/manager-api';
addons.setConfig({
sidebar: {
showRoots: false,
},
});Collapse Roots by Default
addons.setConfig({
sidebar: {
showRoots: true,
collapsedRoots: ['other', 'experimental'],
},
});Custom Sidebar Labels
addons.setConfig({
sidebar: {
renderLabel: (item) => <span>{item.name}</span>,
},
});Story Permalinks
Storybook generates unique IDs from title + name for use in URLs. Preserve a permalink when renaming by setting id manually:
// components/modals/Alert.stories.ts
const meta = {
title: 'Components/Modals/AlertRenamed',
component: Alert,
id: 'Components/Modals/Alert', // preserves old permalink
} satisfies Meta<typeof Alert>;Auto-Title (CSF 3.0)
CSF 3.0 generates titles automatically from file paths. Features:
- Preserves filename casing (as of Storybook 6.5)
- Removes redundant names (e.g.,
MyComponent/MyComponent→MyComponent) - Supports
titlePrefixin story configuration objects
// stories config with titlePrefix
stories: [
{
directory: '../packages/components',
files: '*.stories.*',
titlePrefix: 'MyComponents',
},
]Notes
- Recommended pattern: match title to file path — if file is
components/modals/Alert.stories.js, use titleComponents/Modals/Alert - Story titles use forward slashes to create sidebar nesting
- Custom Story Indexers allow adjusting automatic title generation beyond simple prefixes
Related
- Features and Behavior
- Theming
Story Layout
Control how stories are positioned within Storybook's Canvas tab using the layout parameter.
Overview
The layout parameter provides three display modes for component rendering: centered, fullscreen, and padded (default).
Options
| Value | Description |
|---|---|
'padded' | (Default) Adds surrounding spacing around the component |
'centered' | Centers the component horizontally and vertically in the Canvas |
'fullscreen' | Expands the component across the full width and height of the Canvas |
Configuration
Global (all stories)
// .storybook/preview.ts
import type { Preview } from '@storybook/your-framework';
const preview: Preview = {
parameters: {
layout: 'centered',
},
};
export default preview;Component-level
import type { Meta } from '@storybook/your-framework';
import { Button } from './Button';
const meta = {
component: Button,
parameters: {
layout: 'centered',
},
} satisfies Meta<typeof Button>;
export default meta;Story-level
export const WithLayout: Story = {
parameters: {
layout: 'fullscreen',
},
};Notes
- The parameter cascades: global → component → story; each level overrides the parent
- Use
'fullscreen'for page-level components and layout components - Use
'centered'for isolated UI components like buttons or form inputs
Related
- Story Rendering
- Features and Behavior
Story Rendering
Control how stories are rendered in Storybook's preview iframe (Canvas).
Overview
Stories render within a preview iframe inside the larger Storybook application. You can run code globally for every story or inject custom HTML into the iframe's <head> and <body>.
Configuration
Run Code for Every Story
Code in .storybook/preview.ts executes for all stories globally. Use it for global setup, library initialization, or CSS imports.
// .storybook/preview.ts
import type { Preview } from '@storybook/your-framework';
import { initialize } from '../lib/your-library';
initialize();
const preview: Preview = {
// decorators, parameters, globalTypes, etc.
};
export default preview;Add to <head> — preview-head.html
<!-- .storybook/preview-head.html -->
<link rel="preload" href="/fonts/my-font.woff2" />
<script src="https://use.typekit.net/xxxyyy.js"></script>
<script>
try {
Typekit.load();
} catch (e) {}
</script>Add to <body> — preview-body.html
<!-- .storybook/preview-body.html -->
<div id="custom-root"></div>
<style>
html {
font-size: 15px;
}
</style>Notes
preview-head.htmlandpreview-body.htmlinject into the preview iframe, not the main Storybook UI- Use
preview.tsfor setup that needs HMR support - The JavaScript build configuration is managed by the selected builder (Webpack or Vite)
Related
- Styling and CSS
- Images and Assets
- Story Layout
Styling and CSS
Configure CSS and styling in Storybook to match your application's styling approach.
Overview
Storybook supports multiple CSS inclusion methods. The recommended approach is importing CSS in .storybook/preview.ts for hot module replacement (HMR) support. For external resources without HMR needs, use .storybook/preview-head.html.
Configuration
Import CSS in preview.ts (Recommended)
// .storybook/preview.ts
import type { Preview } from '@storybook/your-framework';
import '../src/styles/global.css';
const preview: Preview = {
parameters: {},
};
export default preview;Static CSS via preview-head.html
<!-- .storybook/preview-head.html -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="stylesheet" href="path/to/your/styles.css" />CSS Processing Tools
| Tool | Vite | Webpack |
|---|---|---|
| CSS Modules | Built-in, no config needed | Requires @storybook/addon-styling-webpack |
| PostCSS | Automatically applied | Requires @storybook/addon-styling-webpack |
| Sass / Less / Stylus | Built-in | Requires @storybook/addon-styling-webpack or custom loaders |
Next.js
Storybook automatically recreates Next.js configuration, so CSS modules work without additional setup.
CSS-in-JS
Most CSS-in-JS solutions work without additional configuration. For theme-dependent libraries, use @storybook/addon-themes's withThemeFromJSXProvider decorator.
Web Fonts
<!-- .storybook/preview-head.html -->
<link rel="preload" href="/fonts/my-font.woff2" />Or import via fontsource packages in preview.ts.
Notes
- CSS imported in
preview.tssupports HMR; changes reflect without server restart - CSS added via
preview-head.htmlrequires a server restart to take effect - Component-level CSS imports work automatically when using the
preview.tsimport approach
Related
- Story Rendering
- Images and Assets
Telemetry
Configure Storybook's anonymous usage data collection.
Overview
Storybook collects completely anonymous telemetry data to help the development team prioritize improvements and stay aligned with ecosystem trends. No personally identifiable information is collected.
What Is Tracked
- Commands executed (
init,dev,build, etc.) - Framework and builder information (React, Vue, Webpack, Vite)
- Addon usage and testing tools
- Story counts and project metadata
- Package manager and monorepo configuration
- One-way hash of IP address (for spam detection only)
Opting Out
Three methods to disable telemetry:
Configuration File
// .storybook/main.ts
import type { StorybookConfig } from '@storybook/your-framework';
const config: StorybookConfig = {
core: {
disableTelemetry: true,
},
};
export default config;CLI Flag
storybook dev --disable-telemetry
storybook build --disable-telemetryEnvironment Variable
STORYBOOK_DISABLE_TELEMETRY=1 storybook devCrash Reporting
Crash reports are disabled by default. Enable via:
core: {
enableCrashReports: true,
}Or per-command:
storybook dev --enable-crash-reportsNotes
- Telemetry applies to all CLI commands unless opted out
- Crash reports send sanitized error data alongside telemetry events
- Data is anonymized and cannot be traced back to individual users or projects
Related
- core
- Environment Variables
Theming
Note: This page has moved to /docs/configure/user-interface/theming in the current documentation.Customize Storybook's UI appearance using the built-in theming API.
Overview
Storybook provides a lightweight theming API with built-in light, dark, and system-preference themes. Themes can be extended via create() or replaced entirely with a custom theme object.
Configuration
Apply a Built-in Theme
// .storybook/manager.js
import { addons } from 'storybook/manager-api';
import { themes } from 'storybook/theming';
addons.setConfig({
theme: themes.dark,
});Theme the Docs Separately
// .storybook/preview.ts
import type { Preview } from '@storybook/your-framework';
import { themes } from 'storybook/theming';
const preview: Preview = {
parameters: {
docs: {
theme: themes.dark,
},
},
};
export default preview;Create a Custom Theme
// .storybook/theme.js
import { create } from 'storybook/theming';
export default create({
base: 'light', // required: 'light' or 'dark'
brandTitle: 'My custom Storybook',
brandUrl: 'https://example.com',
brandImage: 'https://example.com/logo.png',
brandTarget: '_self',
});Theme Variables
| Category | Variables |
|---|---|
| Branding | brandTitle, brandUrl, brandImage, brandTarget |
| Typography | fontBase, fontCode |
| Colors | colorPrimary, colorSecondary, textColor, textInverseColor |
| UI Background | appBg, appContentBg, appPreviewBg |
| UI Borders | appBorderColor, appBorderRadius |
| Toolbar/Nav | barBg, barTextColor, barSelectedColor, barHoverColor |
| Forms | inputBg, inputBorder, inputTextColor, inputBorderRadius |
Advanced CSS Overrides
For fine-grained control beyond the theming API:
<!-- .storybook/manager-head.html (Storybook UI) -->
<!-- .storybook/preview-head.html (Docs) -->
<style>
/* Target internal class names */
</style>MDX Component Overrides
const preview: Preview = {
parameters: {
docs: {
components: {
code: CustomCodeBlock,
Canvas: CustomCanvas,
},
},
},
};For Addon Developers
import { styled } from 'storybook/theming';
const Component = styled.div(({ theme }) => ({
background: theme.background.app,
}));Notes
- When setting a theme, you must provide a complete theme object; partial updates are not merged
- The
baseproperty is mandatory when creating custom themes - CSS class-name targeting is fragile; internal HTML structures may change across releases
- The UI theme and docs theme are configured independently
Related
- Features and Behavior
- Addons
TypeScript
Note: This page has moved to /docs/configure/integration/typescript in the current documentation.Storybook provides zero-configuration TypeScript support with type-safe story authoring.
Overview
The main configuration file (main.ts) is written in TypeScript as an ESM module, enabling strict type-checking and IDE autocompletion out of the box.
Configuration
// .storybook/main.ts
import type { StorybookConfig } from '@storybook/your-framework';
const config: StorybookConfig = {
framework: '@storybook/your-framework',
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
addons: ['@storybook/addon-docs'],
staticDirs: ['../public'],
};
export default config;TypeScript Options
Configure TypeScript behavior under the typescript key in main.ts:
| Option | Type | Description |
|---|---|---|
check | boolean | Enable type checking within Storybook (Webpack only) |
checkOptions | object | Configure fork-ts-checker-webpack-plugin |
reactDocgen | string \ | false |
reactDocgenTypescriptOptions | object | Configure react-docgen-typescript-plugin |
skipCompiler | boolean | Disable TypeScript file parsing through the compiler |
Writing Type-Safe Stories
import type { Meta, StoryObj } from '@storybook/your-framework';
import { Button } from './Button';
const meta = {
component: Button,
} satisfies Meta<typeof Button>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Primary: Story = {
args: {
primary: true,
},
};The satisfies operator (TypeScript 4.9+) provides stricter type checking and notifies developers of missing required arguments.
Notes
- Types not generated for external packages: switch to
react-docgen-typescriptwith custom compiler options - Components with
forwardReforEnumsmay requirereact-docgen-typescriptfor proper type inference - Angular and Web Components frameworks may have constraints when applying
satisfiesdue to difficulty determining required properties
Related
- Frameworks
- Compilers
Actions
Tracks when event handlers are invoked and displays their arguments in the actions panel. Functions as a mock/spy system for component event callbacks.
Overview
Actions log calls made to event handler args, showing event names and argument values in a collapsible tree view. Supports both explicit fn() spies and automatic matching via argTypesRegex.
Configuration
Parameters (parameters.actions)
| Name | Type | Default | Description |
|---|---|---|---|
argTypesRegex | string | — | Regex to auto-create actions for matching arg names (e.g. '^on.*') |
disable | boolean | false | Disables the actions panel |
expandLevel | number | 1 | Initial tree expansion depth for nested action arguments |
Usage
Recommended: fn() from storybook/test
import { fn } from 'storybook/test';
import type { Meta } from '@storybook/react';
import { Button } from './Button';
const meta = {
component: Button,
args: { onClick: fn() },
} satisfies Meta<typeof Button>;Via action() helper
import { action } from 'storybook/actions';
const meta = {
component: Button,
args: { onClick: action('on-click') },
};Via argTypesRegex (global)
// .storybook/preview.ts
const preview: Preview = {
parameters: {
actions: { argTypesRegex: '^on.*' },
},
};Spying on arbitrary calls
import { spyOn } from 'storybook/test';
const preview: Preview = {
async beforeEach() {
spyOn(console, 'log').mockName('console.log');
},
};Notes
- Use
fn()(notargTypesRegex) when stories have play functions — auto-matched args are not available as spies insideplay. - Actions display both event names and argument values in the panel.
- Actions log automatically on user interaction or when triggered from a play function.
Related
- Controls
- Toolbars & Globals
Backgrounds
Sets the background color behind stories in the Storybook UI, enabling visual testing against different color schemes.
Overview
The backgrounds addon adds a toolbar control for switching the canvas background color. Default options include light and dark. Colors can be pinned per story via globals to prevent toolbar changes.
Configuration
Global setup (.storybook/preview.ts)
import type { Preview } from '@storybook/react';
const preview: Preview = {
parameters: {
backgrounds: {
options: {
dark: { name: 'Dark', value: '#333' },
light: { name: 'Light', value: '#F7F9F2' },
maroon: { name: 'Maroon', value: '#400' },
},
},
},
initialGlobals: {
backgrounds: { value: 'light' },
},
};Parameters (parameters.backgrounds)
| Name | Type | Description |
|---|---|---|
options | Record<string, { name: string; value: string }> | Available background colors |
disable | boolean | Disables the addon for the story/component |
grid | object | Grid overlay configuration (see below) |
Grid options
| Name | Type | Description |
|---|---|---|
cellSize | number | Size of each grid cell in px |
opacity | number | Grid opacity (0–1) |
cellAmount | number | Number of subdivisions per cell |
offsetX | number | Horizontal offset in px |
offsetY | number | Vertical offset in px |
Usage
Lock background for a specific story
export const OnDark: Story = {
globals: {
backgrounds: { value: 'dark' },
},
};When set via globals, the background is applied and cannot be changed via the toolbar.
Disable for a story
export const Large: Story = {
parameters: {
backgrounds: { disable: true },
},
};Notes
- Setting
globals.backgrounds.valuein a story locks the background and disables the toolbar control for that story. - The grid overlay is purely visual and does not affect component rendering.
Related
- Controls
- Viewport
- Toolbars & Globals
Measure & Outline
Two complementary toolbar tools for visually inspecting CSS layout, spacing, and alignment inside Storybook stories.
Overview
Measure — hover over elements to see their dimensions, margin, padding, and border sizes rendered as an overlay (similar to browser DevTools box-model view).
Outline — toggles CSS outlines on all UI elements to reveal alignment and spacing issues at a glance.
Configuration
Parameters
Both features accept a disable parameter under their own namespace. The parameter can be set at project, component, or story level.
// Disable at story level
export const MyStory: Story = {
parameters: {
measure: { disable: true },
outline: { disable: true },
},
};| Namespace | Parameter | Type | Description |
|---|---|---|---|
measure | disable | boolean | Disables the measure overlay |
outline | disable | boolean | Disables the outline overlay |
Usage
| Feature | Toolbar action | Keyboard shortcut |
|---|---|---|
| Measure | Click the measure icon | m |
| Outline | Click the outline icon | — |
- Measure: After enabling, hover over any element to inspect its box model.
- Outline: Toggle to draw outlines around every element; toggle again to remove.
Notes
- Both features are enabled by default as part of Storybook Essentials.
- Particularly useful when debugging composite components and page layouts without opening browser DevTools.
- Disabling globally (in
main.tsessentials config) removes the toolbar buttons entirely.
Related
- Highlight
- Viewport