Creates .stories.tsx files for F0 components. For MDX docs (the Docs tab), use the global factorial-f0-component-documentation skill instead — that's a separate file.
Quick Reference
| Need | See |
|---|---|
| Meta definition, tags, argTypes, Snapshot, decorators, play functions | references/story-patterns.md |
| Play functions, portal queries, step(), a11y configuration | Load the f0-storybook-testing skill |
Key Rules
Imports
import type { Meta, StoryObj } from "@storybook/react-vite";
import { fn, expect, within } from "storybook/test";
import { withSnapshot, withSkipA11y } from "@/lib/storybook-utils/parameters";
// Icons: "@/icons/app" | "@/icons/modules" | "@/icons/ai"
Meta
Always satisfies Meta<typeof Component> (not as Meta). Exception: components with complex generics use plain Meta.
const meta = {
title: "ComponentName",
component: F0Example,
tags: ["stable", "!autodocs"], // or "experimental" | "internal" | "deprecated". Always include "!autodocs" when a manual MDX page exists.
// ...
} satisfies Meta<typeof F0Example>;
export default meta;
type Story = StoryObj<typeof meta>;
Snapshots are OFF by default
Chromatic snapshots are globally disabled. Every story that should be captured must opt in:
export const Snapshot: Story = {
parameters: withSnapshot({}), // opt in
};
// With a11y skip: withSkipA11y(withSnapshot({}))
Tags
| Tag | When | Sidebar |
|---|---|---|
"stable" |
Production-ready | ✅ toolbar only |
"experimental" |
Still stabilizing | 🚧 sidebar + toolbar |
"internal" |
Not public | 🔒 sidebar + toolbar |
"deprecated" |
Avoid using | ⛔ sidebar + toolbar |
"!autodocs" |
Manual MDX page exists | Prevents duplicate autogenerated Docs page |
"no-sidebar" |
Hide story from sidebar | Hidden from Storybook navigation |
Note: Storybook applies
tags: ["autodocs"]globally via.storybook/preview.tsx. To opt out of autodocs when a manual MDX page exists, add"!autodocs"to the meta tags. Removing"autodocs"alone is not enough.
ArgTypes for union props
Reference the component's exported const array — don't hardcode the options:
import { buttonSizes, buttonVariants } from "../F0Example"
argTypes: {
size: {
control: "select",
options: buttonSizes,
table: { type: { summary: buttonSizes.join(" | ") } },
},
}
Render-only stories must include args
Stories that use a custom render function without inheriting args from the meta
must include an explicit args property to satisfy the Story type constraint.
Omitting args causes a TypeScript error when the meta has required props.
// WRONG — TS error: Property 'args' is missing
export const Variants: Story = {
tags: ["!dev"],
render: () => <div>...</div>,
};
// CORRECT — provide required args even if render ignores them
export const Variants: Story = {
tags: ["!dev"],
args: { items: [], onClick: () => {} }, // satisfy required props from Meta
render: () => <div>...</div>,
};