> **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/api.md`), Version 9 (`/docs/9/writing-stories/csf/api.md`), Version 8 (`/docs/8/writing-stories/csf/api.md`)

# Component Story Format (CSF)

The CSF 4 API is composed of functions to help you write stories and the annotations used to configure them. Note how three of the functions operate as factories, each producing the next function in the chain (`definePreview` → `preview.meta` → `meta.story`), providing full type safety at each step.

This API reference only documents 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).

## `defineMain`

Type: `(config: StorybookConfig) => StorybookConfig`

The [main Storybook config](https://storybook.js.org/docs/11/api/main-config/main-config.md) is specified by the `defineMain` function. This function is type-safe and will automatically infer types for your project.

```ts
// .storybook/main.js|ts
// Replace your-framework with the framework you are using (e.g., nextjs-vite, sveltekit, etc.)

export default defineMain({
  framework: '@storybook/your-framework',
  stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
  addons: ['@storybook/addon-a11y'],
});
```

## `definePreview`

Type: `(annotations: Annotations) => Preview`

The `definePreview` function specifies your project's story configuration. This function is also type-safe and will infer types throughout your project.

It accepts an object containing the [annotations](#annotations) to apply to all stories in the project.

`addons` is a particularly important annotation to specify. Any addon you include here will have their types available throughout your project, enabling autocompletion and type checking.

The function returns a preview object, which contains the [`meta` function](#previewmeta) used to define story metadata.

```ts
// .storybook/preview.ts|tsx
// Replace your-framework with the framework you are using (e.g., nextjs-vite, sveltekit, etc.)

export default definePreview({
  // 👇 Add your addons here
  addons: [addonA11y()],
  parameters: {
    // type-safe!
    a11y: {
      options: { xpath: true },
    },
  },
});
```

The preview configuration will be automatically updated to reference the necessary addons when installing an addon via `npx storybook add <addon-name>` or running `storybook dev`.

<details>
<summary>Which addons should be specified in `preview`?</summary>

The ability for an addon to provide annotation types (`parameters`, `globals`, etc.) is new and not all addons support it yet.

If an addon provides annotations (i.e. it distributes a `./preview` export), it can be imported in two ways:

1. For official Storybook addons, you import the default export:
   `import addonName from '@storybook/addon-name'`

2. For community addons, you should import the entire module and access the addon from there:
   `import * as addonName from 'community-addon-name'`

</details>

## `preview.meta`

Type: `(annotations: Annotations) => Meta`

The `meta` function on the [`preview`](#definepreview) object is used to define the metadata for your stories. It accepts an object containing the [`component`](#component), [`title`](#title), and other [annotations](#annotations).

The `component` field is used to render your component (unless a [custom render function](https://storybook.js.org/docs/11/writing-stories/csf/index.md#custom-render-functions) is provided). It is also used for automatic prop table generation and display of other component metadata.

The `title` field is optional and should be unique (i.e., not re-used across files). If you don't specify one, it can be inferred from the story's path on disk. For more information, see the section on [configuring story loading](https://storybook.js.org/docs/11/configure/index.md#configure-story-loading).

The function returns a meta object, which contains the [`story` function](#metastory) used to define stories.

```ts
// Button.stories.js|ts

const meta = preview.meta({
  component: Button,
  parameters: {
    // type-safe!
    layout: 'centered',
  },
});
```

### `preview.type.meta`

By default, [`preview.meta`](#previewmeta) will infer the type of your component's props automatically. However, if you need to extend or modify the inferred types, you can use the `preview.type` function to specify custom types. The props of the component are still inferred, so the type only has to hold the args that you add.

```tsx
// Button.stories.ts|tsx

type CustomArgs = { icon: 'check' | 'heart' | 'star' };

const meta = preview.type<{ args: CustomArgs }>().meta({
  component: Button,
  // 👇 Correct types
  render: ({ children, icon, ...args }) => (
    
       {children}
    
  ),
});

export const Primary = meta.story({
  // 👇 Correct types
  args: {
    children: 'Button',
    icon: 'star',
  },
});
```

Every key in the `args` of `preview.meta` must be an arg of your stories: a prop of the component, an arg of its typed `render` function, an arg used by one of its decorators, or an arg declared with `preview.type`. The values are checked against those types, so literal values like `variant: 'primary'` need no `as const`.

For more information on typing your stories, refer to the [writing stories in TypeScript guide](https://storybook.js.org/docs/11/writing-stories/typescript.md).

## `meta.story`

Type: (annotations: Annotations) => Story

Finally, the `story` function on the [`meta`](#previewmeta) object defines the stories. This function accepts an object containing the [`args`](#args), [`parameters`](#parameters), and other story [annotations](#annotations).

```ts
// Button.stories.js|ts
// ...from above
const meta = preview.meta({
  //...
});

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

### `meta.type.story`

Stories take their types from the [meta](#previewmeta). When a single story needs something the other stories of the file don't have, such as an extra arg read by its [`render` function](#render) , you can use the `meta.type` function to add it for that story only.

```tsx
// Button.stories.ts|tsx

type CustomArgs = { icon: 'check' | 'heart' | 'star' };

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

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

export const WithIcon = meta.type<{ args: CustomArgs }>().story({
  // 👇 `icon` is typed, and required, in this story only
  args: { children: 'Button', icon: 'star' },
  render: ({ children, icon, ...args }) => (
    
       {children}
    
  ),
});
```

`meta.type` accepts the same type argument as [`preview.type`](#previewtypemeta), and the two can be combined.

An arg you add must be set in that story, unless you declare it as optional (`meta.type<{ args: { icon?: string } }>()`). Args that the meta already sets stay optional, except the ones you redeclare in `meta.type`: the story must set those again, because the meta's value was not checked against the new type.

### `<Story>.extend`

You can use the `.extend` method to create a new story based on an existing one, with the option to override or add new properties.

```ts
// Button.stories.js|ts
// ...from above
const meta = preview.meta({
  //...
});

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

export const PrimaryDisabled = Primary.extend({
  args: {
    disabled: true,
  },
});
```

<details>
<summary>Property merging details</summary>

Properties are merged intelligently:

- [`args`](#args) are shallow merged
- [`parameters`](#parameters) are deep merged, except for arrays, which are replaced
- [`decorators`](#decorators) and [`tags`](#tags) are concatenated

```ts title="Button.stories.js|ts"
// ...from above
const meta = preview.meta({
  //...
});

export const Example = meta.story({
  args: {
    primary: true,
    exampleArray: ['a', 'b'],
    exampleObject: { a: 'a', b: 'b' },
  },
  parameters: {
    exampleArray: ['a', 'b'],
    exampleObject: { a: 'a', b: 'b' },
  },
  tags: ['a'],
});

/*
 * 👇 Final values applied:
 *    {
 *      args: {
 *        primary: true,
 *        disabled: true,
 *        exampleArray: ['c'],
 *        exampleObject: { a: 'c' }
 *      },
 *      parameters: {
 *        exampleArray: ['c'],
 *        exampleObject: { a: 'c', b: 'b' }
 *      },
 *      tags: ['a', 'b']
 *    }
 */
export const ExtendedExample = Example.extend({
  args: {
    disabled: true,
    exampleArray: ['c'],
    exampleObject: { a: 'c' },
  },
  parameters: {
    disabled: true,
    exampleArray: ['c'],
    exampleObject: { a: 'c' },
  },
  tags: ['b'],
});
```

</details>

### `<Story>.test`

(⚠️ **Experimental**)

A more ergonomic way to define [tests for your stories](https://storybook.js.org/docs/11/writing-tests.md). While this API is still experimental, it is [documented in the RFC to gather feedback](https://github.com/storybookjs/storybook/discussions/30119) and must be enabled via the [`experimentalTestSyntax` feature flag](https://storybook.js.org/docs/11/api/main-config/main-config-features.md#experimentaltestsyntax).

```ts
// Button.stories.js|ts
// ...from above

export const PrimaryDisabled = Primary.extend({ args: { disabled: true } });

// 👇 .test method: Attach tests to a story
//    The test function can run the same code as the play function
PrimaryDisabled.test('should be disabled', async ({ canvas, userEvent, args }) => {
  const button = await canvas.findByRole('button');
  await userEvent.click(button);

  await expect(button).toHaveAttribute('aria-disabled', 'true');
  await expect(args.onClick).not.toHaveBeenCalled();
});
```

## Annotations

Annotations are metadata to configure and control the behavior of stories. Unless otherwise specified, they can be defined at multiple levels:

1. [Preview](#definepreview): Applies to all stories in your project.
2. [Meta](#previewmeta): Applies to all stories within a single file.
3. [Story](#metastory): Applies to an individual story.

Annotation definitions _cascade_, meaning that story-level annotations override meta-level annotations, and meta-level annotations override preview-level annotations. Some annotations have specific cascading behavior that may differ from this general rule:

- [`args`](#args) are shallow merged
- [`parameters`](#parameters) are deep merged, except for arrays, which are replaced
- [`decorators`](#decorators) and [`tags`](#tags) are concatenated

### `addons`

Type: `Array<PreviewAddonEntry>`

Valid within: [Preview](#definepreview)

_Only supported in CSF 4_

Addons included here will have their types made available to your project.

See [`definePreview`](#definepreview) for more details.

### `afterEach`

Type:

```ts
| (context: StoryContext) => void
| Array<(context: StoryContext) => void>
```

Valid within: [Preview](#definepreview), [Meta](#previewmeta), [Story](#metastory)

Runs after the [play function](#play), for final assertions. Can be async. One function or an array of them.

Do not use this for cleanup operations. Instead, perform any necessary cleanup in the return function of [`beforeAll`](#beforeall) or [`beforeEach`](#beforeeach). This ensures that cleanup happens when it should: before the next story renders instead of immediately after the current story has finished rendering.

```ts
// Page.stories.ts — CSF 4

const meta = preview.meta({
  component: Page,
  // 👇 Runs after each story in this file
  async afterEach(context) {
    console.log(`✅ Tested ${context.name} story`);
  },
});

export const Basic = meta.story({
  async play({ canvas }) {
    // ...
  },
});
```

```ts
// Page.stories.ts — 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: Page,
  // 👇 Runs after each story in this file
  async afterEach(context) {
    console.log(`✅ Tested ${context.name} story`);
  },
} satisfies Meta<typeof Page>;
export default meta;

type Story = StoryObj<typeof meta>;

export const Basic: Story = {
  async play({ canvas }) {
    // ...
  },
};
```

### `args`

Type: `{ [argName: string]: any }`

Valid within: [Preview](#definepreview), [Meta](#previewmeta), [Story](#metastory)

Values passed to the component as props or attributes.

See the [Args guide](https://storybook.js.org/docs/11/writing-stories/args.md) for more details.

```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',
  },
};
```

### `argTypes`

Type: `{ [argName: string]: InputType }`

Valid within: [Preview](#definepreview), [Meta](#previewmeta), [Story](#metastory)

Metadata for each arg, such as its control, description, and options. Storybook infers most of it from the component.

See the [ArgTypes reference](https://storybook.js.org/docs/11/api/arg-types.md) for more details.

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

const meta = preview.meta({
  component: Button,
  argTypes: {
    // 👇 All Button stories expect a label arg
    label: {
      control: 'text',
      description: 'Overwritten description',
    },
  },
});
```

```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, vue3-vite, etc.

const meta = {
  component: Button,
  argTypes: {
    // 👇 All Button stories expect a label arg
    label: {
      control: 'text',
      description: 'Overwritten description',
    },
  },
} satisfies Meta<typeof Button>;

export default meta;
```

### `beforeAll`

Type: `() => (void | (() => void))`

Valid within: [Preview](#definepreview)

Runs once before any story loads. Can be async. Can return a cleanup function, which can also by async. When rendering stories in Storybook, the cleanup function is called before `beforeAll` is called again (i.e. after you make a change to `preview.ts`). When rendering stories in Vitest, the cleanup function is called after all tests in a test file have finished running.

```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({
  async beforeAll() {
    await init();
  },
});
```

```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 = {
  async beforeAll() {
    await init();
  },
};

export default preview;
```

### `beforeEach`

Type:

```ts
| (context: StoryContext) => (void | (() => void))
| Array<(context: StoryContext) => (void | (() => void))>
```

Valid within: [Preview](#definepreview), [Meta](#previewmeta), [Story](#metastory)

Runs before the story renders. Can be async. One function or an array of them. Can return a cleanup function, which can also be async and runs when Storybook tears down the story, just before the next story (or the same story) starts rendering.

```ts
// Page.stories.ts — CSF 4

const meta = preview.meta({
  component: Page,
  // 👇 Set the value of Date for every story in the file
  async beforeEach() {
    MockDate.set('2024-02-14');

    // 👇 Reset the Date after each story
    return () => {
      MockDate.reset();
    };
  },
});

export const Basic = meta.story({
  async play({ canvas }) {
    // ... This will run with the mocked Date
  },
});
```

```ts
// Page.stories.ts — 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: Page,
  // 👇 Set the value of Date for every story in the file
  async beforeEach() {
    MockDate.set('2024-02-14');

    // 👇 Reset the Date after each story
    return () => {
      MockDate.reset();
    };
  },
} satisfies Meta<typeof Page>;
export default meta;

type Story = StoryObj<typeof meta>;

export const Basic: Story = {
  async play({ canvas }) {
    // ... This will run with the mocked Date
  },
};
```

### `component`

Type: Depends on the renderer being used (e.g., `React.ComponentType<any>` for React).

Valid within: [Meta](#previewmeta)

The component that the stories document. Storybook uses it to infer [`argTypes`](#argtypes) and to render stories by default.

```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',
  },
};
```

### `decorators`

Type: Depends on the renderer (e.g., `Array<(Story: () => JSX.Element, context: StoryContext) => JSX.Element>` for React)

Valid within: [Preview](#definepreview), [Meta](#previewmeta), [Story](#metastory)

Functions that wrap the story in extra markup or context. One function or an array of them. Story decorators wrap the story first, then meta decorators, then preview decorators.

See the [Decorators guide](https://storybook.js.org/docs/11/writing-stories/decorators.md) for more details.

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

const meta = preview.meta({
  component: YourComponent,
  decorators: [
    (Story) => (
      <div style={{ margin: '3em' }}>
        
        
      </div>
    ),
  ],
});
```

```tsx
// YourComponent.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: YourComponent,
  decorators: [
    (Story) => (
      <div style={{ margin: '3em' }}>
        
        
      </div>
    ),
  ],
} satisfies Meta<typeof YourComponent>;

export default meta;
```

### `excludeStories`

Type: `string[] | RegExp`

Valid within: [Meta](#previewmeta)

Exports will be checked against this array or regular expression, and any matching exports will not be treated as stories.

See [Non-story exports](https://storybook.js.org/docs/11/writing-stories/csf/index.md#non-story-exports) for more details.

```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,
  },
};
```

### `globals`

Type: `{ [globalName: string]: Value }`

Valid within: [Meta](#previewmeta), [Story](#metastory)

Sets global values for these stories and locks them in the toolbar. The exact type of `Value` depends on the definition of the [`globalType`](#globaltypes) you are setting.

See the [Toolbars & globals guide](https://storybook.js.org/docs/11/essentials/toolbars-and-globals.md#setting-globals-on-a-story) for more details.

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

const meta = preview.meta({
  component: Button,
  globals: {
    // 👇 Set background value for all component stories
    backgrounds: { value: 'gray', grid: false },
  },
});

export const OnDark = meta.story({
  globals: {
    // 👇 Override background value for this story
    backgrounds: { value: 'dark' },
  },
});
```

```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 name of your framework (e.g., react-vite, vue3-vite, etc.)

const meta = {
  component: Button,
  globals: {
    // 👇 Set background value for all component stories
    backgrounds: { value: 'gray', grid: false },
  },
} satisfies Meta<typeof Button>;

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

export const OnDark: Story = {
  globals: {
    // 👇 Override background value for this story
    backgrounds: { value: 'dark' },
  },
};
```

### `globalTypes`

Type: `{ [globalName: string]: ToolbarType }`

Valid within: [Preview](#definepreview)

Defines globals and their toolbar menus.

See the [Toolbars & globals guide](https://storybook.js.org/docs/11/essentials/toolbars-and-globals.md) for more details.

```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({
  globalTypes: {
    theme: {
      description: 'Global theme for components',
      toolbar: {
        // The label to show for this toolbar item
        title: 'Theme',
        icon: 'circlehollow',
        // Array of plain string values or MenuItem shape (see below)
        items: ['light', 'dark'],
        // Change title based on selected value (recommended for consistency with the Storybook UI)
        dynamicTitle: true,
      },
    },
  },
  initialGlobals: {
    theme: 'light',
  },
});
```

```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 = {
  globalTypes: {
    theme: {
      description: 'Global theme for components',
      toolbar: {
        // The label to show for this toolbar item
        title: 'Theme',
        icon: 'circlehollow',
        // Array of plain string values or MenuItem shape (see below)
        items: ['light', 'dark'],
        // Change title based on selected value (recommended for consistency with the Storybook UI)
        dynamicTitle: true,
      },
    },
  },
  initialGlobals: {
    theme: 'light',
  },
};

export default preview;
```

### `id`

Type: `string`

Valid within: [Meta](#previewmeta)

The ID used in story URLs. Must be statically analyzable. Generally not used. Set it to keep URLs the same after you rename a [title](#title).

### `includeStories`

Type: `string[] | RegExp`

Valid within: [Meta](#previewmeta)

Exports will be checked against this array or regular expression, and **only** matching exports will be treated as stories.

See [Non-story exports](https://storybook.js.org/docs/11/writing-stories/csf/index.md#non-story-exports) for more details.

```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,
  },
};
```

### `initialGlobals`

Type: `{ [globalName: string]: { [key: string]: string } }`

Valid within: [Preview](#definepreview)

Starting values for globals, such as theme or locale.

See the [Toolbars & globals guide](https://storybook.js.org/docs/11/essentials/toolbars-and-globals.md) for more details.

```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({
  globalTypes: {
    theme: {
      description: 'Global theme for components',
      toolbar: {
        // The label to show for this toolbar item
        title: 'Theme',
        icon: 'circlehollow',
        // Array of plain string values or MenuItem shape (see below)
        items: ['light', 'dark'],
        // Change title based on selected value (recommended for consistency with the Storybook UI)
        dynamicTitle: true,
      },
    },
  },
  initialGlobals: {
    theme: 'light',
  },
});
```

```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 = {
  globalTypes: {
    theme: {
      description: 'Global theme for components',
      toolbar: {
        // The label to show for this toolbar item
        title: 'Theme',
        icon: 'circlehollow',
        // Array of plain string values or MenuItem shape (see below)
        items: ['light', 'dark'],
        // Change title based on selected value (recommended for consistency with the Storybook UI)
        dynamicTitle: true,
      },
    },
  },
  initialGlobals: {
    theme: 'light',
  },
};

export default preview;
```

### `loaders`

Type: `(context: StoryContext) => { [key: string]: any } | void`

Valid within: [Preview](#definepreview), [Meta](#previewmeta), [Story](#metastory)

Functions that load data before the story renders. Can be async. The results are merged into `context.loaded`.

See the [Loaders guide](https://storybook.js.org/docs/11/writing-stories/loaders.md) for more details.

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

/*
 *👇 Render functions are a framework specific feature to allow you control on how the component renders.
 * See https://storybook.js.org/docs/writing-stories/csf
 * to learn how to use render functions.
 */
const meta = preview.meta({
  component: TodoItem,
  render: (args, { loaded: { todo } }) => ,
});

export const Primary = meta.story({
  loaders: [
    async () => ({
      todo: await (await fetch('https://jsonplaceholder.typicode.com/todos/1')).json(),
    }),
  ],
});
```

```tsx
// 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.

/*
 *👇 Render functions are a framework specific feature to allow you control on how the component renders.
 * See https://storybook.js.org/docs/writing-stories/csf
 * to learn how to use render functions.
 */
const meta = {
  component: TodoItem,
  render: (args, { loaded: { todo } }) => ,
} satisfies Meta<typeof TodoItem>;

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

export const Primary: Story = {
  loaders: [
    async () => ({
      todo: await (await fetch('https://jsonplaceholder.typicode.com/todos/1')).json(),
    }),
  ],
};
```

### `mount`

Type: Depends on the renderer (e.g., `(context: StoryContext) => (ui?: JSX.Element) => Promise<Canvas>` for React)

Valid within: [Preview](#definepreview), [Meta](#previewmeta), [Story](#metastory)

Replaces the function that the [play function](#play) gets as `mount`. The `Canvas` it resolves to has Testing Library queries for the story's root element. Most projects do not need it.

### `name`

Type: `string`

Valid within: [Story](#metastory)

The story's name in the sidebar. If you do not set it, Storybook makes it from the export name.

```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!',
  // ...
};
```

### `parameters`

Type: `{ [name: string]: any }`

Valid within: [Preview](#definepreview), [Meta](#previewmeta), [Story](#metastory)

Static metadata, usually for addons and features. Storybook deep-merges it from preview to meta to story.

See the [Parameters guide](https://storybook.js.org/docs/11/writing-stories/parameters.md) for more details.

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

const meta = preview.meta({
  component: Button,
  //👇 Creates specific parameters at the component level
  parameters: {
    backgrounds: {
      options: {},
    },
  },
});
```

```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, vue3-vite, etc.

const meta = {
  component: Button,
  //👇 Creates specific parameters at the component level
  parameters: {
    backgrounds: {
      options: {},
    },
  },
} satisfies Meta<typeof Button>;

export default meta;
```

### `play`

Type: `(context: StoryContext & { canvas: TestingLibraryCanvas; userEvent: TestingLibraryUserEvent; context: StoryContext }) => void`

Valid within: [Meta](#previewmeta), [Story](#metastory)

Runs after the story renders, to interact with it and make assertions.

See the [Play function guide](https://storybook.js.org/docs/11/writing-stories/play-function.md) for more details.

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

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

export const ExampleStory = meta.story({
  play: async ({ canvas, userEvent }) => {
    // Starts querying from the component's root element
    await userEvent.type(canvas.getByTestId('example-element'), 'something');
    await userEvent.click(canvas.getByRole('button'));
  },
});
```

```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 ExampleStory: Story = {
  play: async ({ canvas, userEvent }) => {
    // Starts querying from the component's root element
    await userEvent.type(canvas.getByTestId('example-element'), 'something');
    await userEvent.click(canvas.getByRole('button'));
  },
};
```

### `render`

Type: Depends on the renderer (e.g., `(args: { [argName: string]: any }, context: StoryContext) => JSX.Element` for React)

Valid within: [Preview](#definepreview), [Meta](#previewmeta), [Story](#metastory)

Sets how the story renders from its args. If you do not set it, Storybook renders the [`component`](#component) with the args.

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

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

// This story uses a render function to fully control how the component renders.
export const Example = meta.story({
  render: () => (
    
      <header>
        <h1>Example</h1>
      </header>
      <article>
        
      </article>
    
  ),
});
```

```tsx
// 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,
} satisfies Meta<typeof MyComponent>;

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

// This story uses a render function to fully control how the component renders.
export const Example: Story = {
  render: () => (
    
      <header>
        <h1>Example</h1>
      </header>
      <article>
        
      </article>
    
  ),
};
```

### `subcomponents`

Type: Depends on the renderer (e.g., `{ [name: string]: React.ComponentType<any> }` for React)

Valid within: [Meta](#previewmeta)

Related components to show in the [Controls table](https://storybook.js.org/docs/11/api/doc-blocks/doc-block-controls.md), each in its own tab.

See the [Stories for multiple components guide](https://storybook.js.org/docs/11/writing-stories/stories-for-multiple-components.md) for more details.

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

const meta = preview.meta({
  component: List,
  subcomponents: { ListItem }, //👈 Adds the ListItem component as a subcomponent
});

export const Empty = meta.story();

export const OneItem = meta.story({
  render: (args) => (
    
      
    
  ),
});
```

```tsx
// List.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: List,
  subcomponents: { ListItem }, //👈 Adds the ListItem component as a subcomponent
} satisfies Meta<typeof List>;
export default meta;

type Story = StoryObj<typeof meta>;

export const Empty: Story = {};

export const OneItem: Story = {
  render: (args) => (
    
      
    
  ),
};
```

### `tags`

Type: `string[]`

Valid within: [Preview](#definepreview), [Meta](#previewmeta), [Story](#metastory)

Apply built-in and custom tags to stories, for example to indicate their status or categorize them. A `!` prefix removes a tag that a higher level added.

See the [Tags guide](https://storybook.js.org/docs/11/writing-stories/tags.md) for more details.

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

const meta = preview.meta({
  component: Button,
  /*
   * All stories in this file will have these tags applied:
   * - autodocs
   * - dev (implicit default, inherited from preview)
   * - test (implicit default, inherited from preview)
   */
  tags: ['autodocs'],
});

export const ExperimentalFeatureStory = meta.story({
  /*
   * This particular story will have these tags applied:
   * - experimental
   * - autodocs (inherited from meta)
   * - dev (inherited from meta)
   * - test (inherited from meta)
   */
  tags: ['experimental'],
});
```

```ts
// Button.stories.ts — 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: Button,
  /*
   * All stories in this file will have these tags applied:
   * - autodocs
   * - dev (implicit default, inherited from preview)
   * - test (implicit default, inherited from preview)
   */
  tags: ['autodocs'],
} satisfies Meta<typeof Button>;

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

export const ExperimentalFeatureStory: Story = {
  /*
   * This particular story will have these tags applied:
   * - experimental
   * - autodocs (inherited from meta)
   * - dev (inherited from meta)
   * - test (inherited from meta)
   */
  tags: ['experimental'],
};
```

### `title`

Type: `string`

Valid within: [Meta](#previewmeta)

Controls where the component appears in the sidebar. Separate levels with `/`. Must be statically analyzable.

If you do not set it, Storybook infers it from the file path of the story file.

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

const meta = preview.meta({
  /* 👇 The title prop is optional.
   * See https://storybook.js.org/docs/configure/#configure-story-loading
   * to learn how to generate automatic titles
   */
  component: MyComponent,
  title: 'components/MyComponent/MyComponent',
});

export const Basic = meta.story({
  args: {
    something: 'Something else',
  },
});
```

```ts
// components/MyComponent/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 = {
  /* 👇 The title prop is optional.
   * See https://storybook.js.org/docs/configure/#configure-story-loading
   * to learn how to generate automatic titles
   */
  component: MyComponent,
  title: 'components/MyComponent/MyComponent',
} satisfies Meta<typeof MyComponent>;

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

export const Basic: Story = {
  args: {
    something: 'Something else',
  },
};
```