Home › Storybook › Storybook 10 stories and tests Cursor rules

Storybook 10 stories and tests Cursor rules

Cursor rules for Storybook 10: CSF 3 stories per component state, args and fn() actions, play-function interaction tests, a11y checks, module mocks, and the Vitest addon.

CursorStorybook

How to use

Save this as .cursor/rules/storybook.mdc in your repository root, commit it, and your agent will pick it up automatically. Edit the commands to match your project.

Note: Review and test before use. Provided as is, without warranty. See Terms.

.cursor/rules/storybook.mdcDownload  
---
description: Storybook 10 story and interaction-test conventions
globs: ["**/*.stories.{ts,tsx,js,jsx,svelte}", "**/*.mdx", ".storybook/**"]
alwaysApply: false
---

# Storybook 10

## Setup
- Storybook 10 is ESM-only. `.storybook/main.ts` and `.storybook/preview.ts` use `import` / `export default`; no `require()` or `module.exports`. It needs Node 20.16+, 22.19+ or 24+.
- Use the framework package that matches the app (`@storybook/react-vite`, `@storybook/nextjs-vite`, `@storybook/vue3-vite`, `@storybook/sveltekit`, `@storybook/angular`) and import `Meta` / `StoryObj` types from it.
- Global providers (theme, router, i18n, query client) go in `preview.ts` decorators. Add per-story decorators only for exceptions.

## Writing stories
- Colocate `Button.stories.tsx` next to `Button.tsx`. Let Storybook derive the sidebar title from the path; don't set `title` unless the repo already does.
- Default to CSF 3:
  ```ts
  const meta = { component: Button, args: { label: 'Save' } } satisfies Meta<typeof Button>;
  export default meta;
  type Story = StoryObj<typeof meta>;
  export const Disabled: Story = { args: { disabled: true } };
  ```
  Use CSF Factories (`preview.meta()` / `meta.story()`) only if the repo already uses them. Never mix formats in one file.
- One story per meaningful state: default, each variant, disabled, loading, empty, error, long text or overflow. Name stories after the state (`Loading`), never `Story1`.
- Put shared args on `meta`; each story overrides only what differs. Add `argTypes` only for controls Storybook can't infer.
- Pass handlers as `fn()` from `storybook/test` (`args: { onClick: fn() }`) so they show in the Actions panel and can be asserted.
- Stories never call real APIs. Mock requests with MSW if the repo uses `msw-storybook-addon`, or register module mocks with `sb.mock(...)` in `.storybook/preview.ts`. Keep fixtures in a `__fixtures__` or `mocks/` folder, not inline in every story.
- Add `tags: ['autodocs']` on `meta` when the component needs a docs page. Use MDX only for prose pages, embedding stories with `<Canvas of={...} />`.

## Interaction tests
- Write tests as `play` functions: `play: async ({ canvas, userEvent, args }) => { ... }`.
- Import `expect`, `fn` and `waitFor` from `storybook/test` (the old `@storybook/test` package is pre-9).
- Query like a user: `canvas.getByRole('button', { name: /save/i })`, `getByLabelText`. No CSS selectors or test ids unless there's no accessible name.
- `await` every `userEvent` call and every `expect`. Assert on visible output and on handler calls (`await expect(args.onSubmit).toHaveBeenCalledWith(...)`), not on component internals.

## Accessibility
- Keep `@storybook/addon-a11y` on. Fix violations in the component instead of disabling rules. If one story has a known issue, scope the exception to that story with a comment explaining why.

## Commands
- Dev: `npm run storybook` · Static build: `npm run build-storybook`
- Tests: `npx vitest --project=storybook` (install the runner with `npx storybook add @storybook/addon-vitest`)
- Upgrade: `npx storybook@latest upgrade`

## Done when
New and changed stories render without console errors, `vitest --project=storybook` passes, and the a11y panel shows no new violations.

More: all Storybook rules · all Cursor rules

Related rules

Astro content site rules

Cursor rules for Astro 5 sites with content collections, islands, and zero-JS-by-default pages.

CursorAstro

Chrome extension (Manifest V3) rules

Cursor rules for building Manifest V3 browser extensions with TypeScript and minimal permissions.

CursorChrome extensions

Lit web components rules

Cursor rules for Lit 3 web components in TypeScript: reactive properties, templates, styles, events, and accessibility.

CursorLit / web components

Next.js 16 rules (Cache Components, proxy.ts)

Cursor rules for Next.js 16 App Router: Cache Components with "use cache", proxy.ts, async request APIs, Turbopack.

CursorNext.js

Next.js App Router (TypeScript) rules

Cursor project rules for Next.js 15 App Router apps with TypeScript, Server Components, and Tailwind.

CursorNext.js

Nuxt 3 + Vue rules

Cursor rules for Nuxt 3 / Vue 3 apps using the Composition API, script setup and Pinia.

CursorVue / Nuxt

Get the best new AI prompts every week

One short email a week: the best new prompts and rules for ChatGPT, Claude, Gemini, Midjourney, Cursor and more, plus what changed in the tools. Free, unsubscribe anytime.

Finishes on our newsletter page at beehiiv (opens in a new tab). Or subscribe directly.