f0-storybook-stories

star 25

Create Storybook story files (.stories.tsx) for F0 React components. Use when adding or updating stories, snapshot stories, argTypes, decorators, play functions, or internal stories. For MDX documentation files, use the global factorial-f0-component-documentation skill instead.

factorialco By factorialco schedule Updated 6/10/2026

name: f0-storybook-stories description: Create Storybook story files (.stories.tsx) for F0 React components. Use when adding or updating stories, snapshot stories, argTypes, decorators, play functions, or internal stories. For MDX documentation files, use the global factorial-f0-component-documentation skill instead.

F0 Storybook Stories

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

Why: Chromatic charges per snapshot and visual-diff reviews get noisy when the same component produces many captures. The policy is one consolidated snapshot per component — a single image that shows every meaningful variant in a flex layout — so a visual change produces exactly one diff to review.

Rule: every component has exactly one story exported as Snapshot that opts in with withSnapshot({}). Do not scatter withSnapshot() across multiple stories; consolidate all variants into the Snapshot story.

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. Never apply to the first exported (primary) story when an attached MDX exists — it propagates to the --documentation entry and hides the whole Documentation page.

internal is not a maturity level. Use it for components in src/ui/ (Radix wrappers) and for stories you want hidden from the public Storybook sidebar but visible locally. The three F0 maturity levels are stable, experimental, and deprecated — see Component Maturity.

Promotion and deprecation: when a component is promoted from experimental/ to stable, change the tag from "experimental" to "stable". When deprecating, change to "deprecated" and add @deprecated + @removeIn + @migration JSDoc tags on the export. See the f0-component-promotion skill and the Deprecation & Removal policy.

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.

Manual MDX requires a visible first story

When a component has a manual MDX file (F0Example.mdx with <Meta of={Stories} />), Storybook attaches the MDX docs entry to the first exported story and inherits its tags onto the docs entry.

Consequence: if the first exported story has tags: ["no-sidebar"], the Documentation page also gets no-sidebar and disappears from the sidebar — the MDX is still served but unreachable through navigation.

Rule: with manual MDX, the first exported story must NOT include no-sidebar. Conventionally that first story is Default, and it must remain visible in the sidebar. Hidden helper stories (no-sidebar) referenced by <Canvas of={...} /> come after.

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>,
}
Install via CLI
npx skills add https://github.com/factorialco/f0 --skill f0-storybook-stories
Repository Details
star Stars 25
call_split Forks 4
navigation Branch main
article Path SKILL.md
More from Creator