> **Version 11 (alpha)** — **React** / **TypeScript**
> Also available:
- `?renderer=angular` for angular, html, preact, solid, svelte, vue, web-components
- `?language=js` for JavaScript
- `?codeOnly=true` for code snippets only
- other versions: Version 10.6 (latest) (`/docs/writing-stories/csf.md`), Version 9 (`/docs/9/writing-stories/csf.md`), Version 8 (`/docs/8/writing-stories/csf.md`)

# Component Story Format (CSF)

CSF 4 is supported in [React](https://storybook.js.org/docs/11/writing-stories/csf/?renderer=react.md), [Vue](https://storybook.js.org/docs/11/writing-stories/csf/?renderer=vue.md), [Angular](https://storybook.js.org/docs/11/writing-stories/csf/?renderer=angular.md), [Web Components](https://storybook.js.org/docs/11/writing-stories/csf/?renderer=web-components.md), and [Svelte](https://storybook.js.org/docs/11/writing-stories/csf/?renderer=svelte.md) projects.

Component Story Format (CSF) is the way to write stories for your components in Storybook, providing a standardized and type-safe approach to defining component metadata and story behavior.

This document is primarily a reference for the latest version of the Component Story Format, **CSF 4**. Earlier versions are documented in the [Storybook 10 docs](https://storybook.js.org/docs/10/api/csf.md).

There are two types of files in CSF:

- **Preview file**: This file contains the global configuration for your stories, such as decorators, parameters, and addons. It is typically located in the `.storybook` directory and named `preview.js|jsx` or `preview.ts|tsx`.
- **Story files**: These files define the individual stories for your components. They include the component metadata and the story definitions themselves. Story files usually have the `.stories.js|jsx`, `.stories.ts|tsx`, or `.stories.svelte` extensions.

## Preview file

The preview file contains the configuration for every story in your Storybook project. It can include [addons](https://storybook.js.org/docs/11/writing-stories/csf/api.md#addons), [decorators](https://storybook.js.org/docs/11/writing-stories/decorators.md), [parameters](https://storybook.js.org/docs/11/writing-stories/parameters.md), and other metadata that applies to all stories.

With CSF 4, the preview config is created using the [`definePreview`](https://storybook.js.org/docs/11/writing-stories/csf/api.md#definepreview) function, which provides type safety both in this file and in the story files that consume it.

The properties that define this metadata are called [annotations](https://storybook.js.org/docs/11/writing-stories/csf/api.md#annotations). Most annotations defined here can be overridden in story files.

The preview file must default export a `preview` object.

```ts
// .storybook/preview.tsx — CSF 4
// Replace your-framework with the framework you are using (e.g., react-vite, nextjs, nextjs-vite)

export default definePreview({
  parameters: {
    backgrounds: {
      options: {
        light: { name: 'Light', value: '#fff' },
        dark: { name: 'Dark', value: '#333' },
      },
    },
  },
});
```

```ts
// .storybook/preview.ts|tsx — CSF 3
// ⚠️ CSF versions 1, 2, and 3 will be removed in a future version of Storybook. Upgrade to CSF 4: https://storybook.js.org/docs/writing-stories/csf#upgrade-to-csf-4
// Replace your-framework with the framework you are using, e.g. react-vite, nextjs, vue3-vite, etc.

const preview: Preview = {
  parameters: {
    backgrounds: {
      options: {
        light: { name: 'Light', value: '#fff' },
        dark: { name: 'Dark', value: '#333' },
      },
    },
  },
};

export default preview;
```

## Story files

Story files define a component in Storybook (the `meta` object) and its [stories](https://storybook.js.org/docs/11/writing-stories.md).

### Meta

The `meta` object specifies the component that the stories are for, along with other annotations that apply to all stories within that file and override those defined in the preview file.

With CSF 4, the `meta` object is created using the [`preview.meta`](https://storybook.js.org/docs/11/writing-stories/csf/api.md#previewmeta) function and does not need to be exported. Because it is defined within the preview context, it automatically inherits type safety and other benefits provided by the preview configuration.

CSF 3 and earlier require the default export of `meta`.

### Stories

Each story is a named export within the file, and can include its own annotations, such as `args`, `decorators`, and `parameters`, which override those defined in the `meta` object and the preview file.

With CSF 4, each story is created using the [`meta.story`](https://storybook.js.org/docs/11/writing-stories/csf/api.md#metastory) function. Once again, type safety is automatically inherited from the `meta` object.

```ts
// Button.stories.ts|tsx — CSF 4

const meta = preview.meta({
  component: Button,
});

export const Primary = meta.story({
  args: {
    primary: true,
    label: 'Button',
  },
});
```

```ts
// Button.stories.ts|tsx — CSF 3
// ⚠️ CSF versions 1, 2, and 3 will be removed in a future version of Storybook. Upgrade to CSF 4: https://storybook.js.org/docs/writing-stories/csf#upgrade-to-csf-4
// Replace your-framework with the framework you are using, e.g. react-vite, nextjs, nextjs-vite, etc.

const meta = {
  component: Button,
} satisfies Meta<typeof Button>;

export default meta;
type Story = StoryObj<typeof meta>;

export const Primary: Story = {
  args: {
    primary: true,
    label: 'Button',
  },
};
```

But how does Storybook know how to render your component? By default, Storybook uses the `component` property in the `meta` object to determine which component to render for each story. It then passes along any `args` applied to a story as props or attributes to the component. You can control this behavior by specifying a [custom `render` function](#custom-render-functions).

<a name="subpath-imports" />

If you would like to use absolute imports instead of relative imports for your preview config, like below, you can configure that using subpath imports or an alias.

```ts
// ✅ Absolute imports won't break if you move story files around

// ❌ Relative imports can break if you move story files around

```

<details>
<summary>Configuration</summary>

Subpath imports are a Node.js standard that allows you to define custom import paths in your project, which you can then use throughout your codebase.

To configure subpath imports, add the following to your `package.json`:

```json title="package.json"
{
  "imports": {
    "#*": ["./*", "./*.ts", "./*.tsx"]
  }
}
```

For more information, refer to the [subpath imports documentation](https://storybook.js.org/docs/11/writing-stories/mocking-data-and-modules/mocking-modules.md#subpath-imports).

---

Alternatively, you can [configure an alias in your builder](https://storybook.js.org/docs/11/writing-stories/mocking-data-and-modules/mocking-modules.md#builder-aliases) (Vite or Webpack).

</details>

#### Story configuration

Stories are configured by applying [annotations](https://storybook.js.org/docs/11/writing-stories/csf/api.md#annotations), which are properties in the story object that define their behavior and supply metadata. Some common annotations are:

- [`args`](https://storybook.js.org/docs/11/writing-stories/csf/api.md#args): Define the arguments (props) for the story, which can be controlled dynamically in the Storybook UI.
- [`parameters`](https://storybook.js.org/docs/11/writing-stories/csf/api.md#parameters): Pass additional metadata and configuration options to the story.
- [`decorators`](https://storybook.js.org/docs/11/writing-stories/csf/api.md#decorators): Wrap stories with additional markup or context, such as context providers or layout components.
- [`play`](https://storybook.js.org/docs/11/writing-stories/csf/api.md#play): Define interactions and tests for the story after it has rendered.
- [`tags`](https://storybook.js.org/docs/11/writing-stories/csf/api.md#tags): Assign tags to the story for categorization or filtering purposes.

In addition to configuring individual stories, nearly all annotations can be defined at the meta level (which applies to all stories of the component) or at the preview level (which applies globally to all stories in the Storybook). Annotations defined at the story level will override or merge with those defined at the meta level, which override or merge with those defined at the preview level.

#### Story names

For a story's display name, the exported identifiers will be converted to "start case" similar to Lodash's [startCase](https://lodash.com/docs/#startCase) function. For example:

| Identifier       | Transformation    |
| ---------------- | ----------------- |
| name             | Name              |
| someName         | Some Name         |
| someNAME         | Some NAME         |
| some_custom_NAME | Some Custom NAME  |
| someName1234     | Some Name 1 2 3 4 |

We recommend that all export names to start with a capital letter.

You can also customize the display name of a story by using the [`name`](https://storybook.js.org/docs/11/writing-stories/index.md#rename-stories) property within the story object. There are two main cases where this is useful:

1. You want the name to show up in the Storybook UI in a way that's not possible with a named export, e.g., reserved keywords like "default", special characters like emoji, spacing/capitalization other than what's provided by the default transformation.
2. You want to preserve the Story ID independently from changing how it's displayed. Having stable Story IDs is helpful for integration with third-party tools.

```tsx
// MyComponent.stories.ts|tsx — CSF 4

const meta = preview.meta({
  component: MyComponent,
});

export const Simple = meta.story({
  name: 'So simple!',
  // ...
});
```

```ts
// MyComponent.stories.ts|tsx — CSF 3
// ⚠️ CSF versions 1, 2, and 3 will be removed in a future version of Storybook. Upgrade to CSF 4: https://storybook.js.org/docs/writing-stories/csf#upgrade-to-csf-4
// Replace your-framework with the framework you are using, e.g. react-vite, nextjs, vue3-vite, etc.

const meta = {
  component: MyComponent,
} satisfies Meta<typeof MyComponent>;

export default meta;
type Story = StoryObj<typeof meta>;

export const Simple: Story = {
  name: 'So simple!',
  // ...
};
```

### Custom render functions

[`render` functions](https://storybook.js.org/docs/11/writing-stories/csf/api.md#render) give you additional control over how the story renders. For example, if you have a `Button` component and you want to have it rendered within an `Alert`, you could write the following:

```tsx
// Button.stories.tsx — CSF 4

const meta = preview.meta({
  component: Button,
  render: (args) => (
    
      Alert text
      
    
  ),
});

export const DefaultInAlert = meta.story({
  args: {
    label: 'Button',
  },
});

export const PrimaryInAlert = meta.story({
  args: {
    primary: true,
    label: 'Button',
  },
});
```

```tsx
// Button.stories.tsx — CSF 3
// ⚠️ CSF versions 1, 2, and 3 will be removed in a future version of Storybook. Upgrade to CSF 4: https://storybook.js.org/docs/writing-stories/csf#upgrade-to-csf-4
// Replace your-framework with the framework you are using, e.g. react-vite, nextjs, nextjs-vite, etc.

const meta = {
  component: Button,
  render: (args) => (
    
      Alert text
      
    
  ),
} satisfies Meta<typeof Button>;
export default meta;

type Story = StoryObj<typeof meta>;

export const DefaultInAlert: Story = {
  args: {
    label: 'Button',
  },
};

export const PrimaryInAlert: Story = {
  args: {
    primary: true,
    label: 'Button',
  },
};
```

Note that `args` are available as the `render` function's first argument. Typically you'll pass them to your component(s) to control its rendering. But you can also use them in any way you need within the `render` function.

The example above demonstrates how to define a custom render function at the meta level, which will be applied to all stories of the component. You can also specify a `render` function for individual stories if you need different rendering behavior for specific cases.

```tsx
// Button.stories.tsx — CSF 4

const meta = preview.meta({
  component: Button,
});

export const PrimaryInAlert = meta.story({
  args: {
    primary: true,
    label: 'Button',
  },
  render: (args) => (
    
      Alert text
      
    
  ),
});
```

```tsx
// Button.stories.tsx — CSF 3
// ⚠️ CSF versions 1, 2, and 3 will be removed in a future version of Storybook. Upgrade to CSF 4: https://storybook.js.org/docs/writing-stories/csf#upgrade-to-csf-4
// Replace your-framework with the framework you are using, e.g. react-vite, nextjs, nextjs-vite, etc.

const meta = {
  component: Button,
} satisfies Meta<typeof Button>;
export default meta;

type Story = StoryObj<typeof meta>;

export const PrimaryInAlert: Story = {
  args: {
    primary: true,
    label: 'Button',
  },
  render: (args) => (
    
      Alert text
      
    
  ),
};
```

### Non-story exports

In some cases, you may want to export a mixture of stories and non-stories (e.g., mocked data).

You can use the optional configuration fields `includeStories` and `excludeStories` in the `meta` to make this possible. You can define them as an array of strings or regular expressions.

Consider the following story file:

```tsx
// MyComponent.stories.ts|tsx — CSF 4

const meta = preview.meta({
  component: MyComponent,
  includeStories: ['SimpleStory', 'ComplexStory'], // 👈 Storybook loads these stories
  excludeStories: /.*Data$/, // 👈 Storybook ignores anything that contains Data
});

export const simpleData = { foo: 1, bar: 'baz' };
export const complexData = { foo: 1, foobar: { bar: 'baz', baz: someData } };

export const SimpleStory = meta.story({
  args: {
    data: simpleData,
  },
});

export const ComplexStory = meta.story({
  args: {
    data: complexData,
  },
});
```

```ts
// MyComponent.stories.ts|tsx — CSF 3
// ⚠️ CSF versions 1, 2, and 3 will be removed in a future version of Storybook. Upgrade to CSF 4: https://storybook.js.org/docs/writing-stories/csf#upgrade-to-csf-4
// Replace your-framework with the framework you are using, e.g. react-vite, nextjs, nextjs-vite, etc.

const meta = {
  component: MyComponent,
  includeStories: ['SimpleStory', 'ComplexStory'], // 👈 Storybook loads these stories
  excludeStories: /.*Data$/, // 👈 Storybook ignores anything that contains Data
} satisfies Meta<typeof MyComponent>;

export default meta;
type Story = StoryObj<typeof meta>;

export const simpleData = { foo: 1, bar: 'baz' };
export const complexData = { foo: 1, foobar: { bar: 'baz', baz: someData } };

export const SimpleStory: Story = {
  args: {
    data: simpleData,
  },
};

export const ComplexStory: Story = {
  args: {
    data: complexData,
  },
};
```

When this file renders in Storybook, it treats `ComplexStory` and `SimpleStory` as stories and ignores the `data` named exports.

For this particular example, you could achieve the same result in different ways, depending on what's convenient:

- `includeStories: /^[A-Z]/`
- `includeStories: /.*Story$/`
- `includeStories: ['SimpleStory', 'ComplexStory']`
- `excludeStories: /^[a-z]/`
- `excludeStories: /.*Data$/`
- `excludeStories: ['simpleData', 'complexData']`

The first option is the recommended solution if you follow the best practice of starting story exports with an uppercase letter (i.e., use UpperCamelCase).

## Frequently asked questions (FAQ)

### Will I have to migrate all of my stories to this new format?

Storybook will continue to support CSF 1, [CSF 2](https://storybook.js.org/docs/6/api/stories/csf.md), and [CSF 3](https://storybook.js.org/docs/10/api/csf.md) for the foreseeable future. None of these prior formats are deprecated.

While using CSF 4, you can still use the older formats, as long as they are not mixed in the same file. If you want to migrate your existing files to the new format, refer to [the upgrade guide](https://storybook.js.org/docs/11/writing-stories/csf/upgrade.md).

### How do I use custom arg types with this format?

The [`preview.type`](https://storybook.js.org/docs/11/writing-stories/csf/api.md#previewtypemeta) function allows you to specify custom types for your story's args, which can be used to provide type safety for custom arg types. To specify them for a single story, use the [`meta.type`](https://storybook.js.org/docs/11/writing-stories/csf/api.md#metatypestory) function.

### Will this format work with MDX docs pages?

Yes, the [doc blocks](https://storybook.js.org/docs/11/writing-docs/doc-blocks.md) used to reference stories in MDX files support the CSF 4 format with no changes needed.