SuperAPI AI Directory

storybook

Testing & quality

View repository

Updated 10-16 01:29

About this skill

Storybook

Scaffold and test Storybook stories — three artefacts in two files per component: a Default story and a Playground story (both in the visual regression file) plus an interaction test file under a /Tests namespace. Works on React (web) and React Native / Expo (native). Auth — when the running Storybook is gated — is opt-in and per-pathname, with secrets stored in the OS keychain instead of the repo.

This SKILL.md is a thin index. Concern-specific rules live in rules/*.md and load on demand. Reference material lives in references/*.md. Literal scaffolding lives in templates/*.md. Do not preload every file — load only what the current phase asks for.


When to use

Reach for this skill when any of the following is true:

  • A component has no story file yet and needs visual regression coverage.
  • An existing *.stories.tsx lacks an interaction test counterpart.
  • A Playground story is missing or out of sync with current props.
  • The Storybook target is gated by auth and the agent needs to log in.
  • A flaky interaction test needs to be iterated against the running Storybook URL.

Do not reach for this skill when:

  • The task is to build the component itself. Scaffold stories after the component is implemented and named.
  • The repo has no Storybook installation at all. Halt and ask the user to install Storybook first — this skill does not bootstrap Storybook.
  • The component is a hook or non-visual primitive with no rendered surface. Defer to tdd.

Arguments and defaults

Parse $ARGUMENTS in this order:

Argument Default Effect
<component-path> Prompt the user Source file of the component to scaffold stories for.
--platform web|native Auto-detect (see rules/react-native.md) Web emits .stories.tsx; native emits the Expo / RN variant.
--no-interactions Generate <name>.test.stories.tsx Skip the interaction test file.
--no-playground Include a Playground story Skip the Playground story.
--no-default Include a Default story with grouped variants Skip the visual regression Default story (rare — only for test-only).
--validate Off Run the opt-in adversarial validate-and-fix phase (Phase 6) after the scaffold. Local only.
--auth <profile> None Use the named auth profile when running Playwright against the URL.
--title <storybook-title> Inferred from the component path Override the Storybook title for the generated meta.

Sub-commands:

/storybook validate <component>     # Run only the adversarial validate-and-fix phase against an existing story.
/storybook auth list                # List configured auth profiles in this repo.
/storybook auth add <profile>       # Register a new profile (writes config + stores secret in OS keychain).
/storybook auth remove <profile>    # Remove a profile (deletes config entry + keychain item).
/storybook auth test <profile>      # Dry-run the login flow against the configured URL.

/storybook validate <component> skips scaffolding: it reads the existing .stories.tsx / .test.stories.tsx and runs Phase 6 directly. The full loop — probe catalog, triage, confidence-gated fixes — lives in rules/adversarial-validation.md.

The full auth contract — config schema, keychain commands per OS, and the storageState reuse loop — lives in rules/auth.md.


Workflow (six phases + opt-in validation)

Each phase has a single gate. Do not proceed until it passes. Phase 6 runs only when --validate is passed or the skill is invoked as /storybook validate <component>.

Phase Name Gate
0 Preflight Storybook installed; platform detected; auth profile loaded if asked
1 Component inspection Component file read; props and variants enumerated
2 Visual regression scaffold <name>.stories.tsx written; variants grouped
3 Playground scaffold Playground story written with args + argTypes
4 Interaction test scaffold <name>.test.stories.tsx written under /Tests namespace
5 Verification Storybook running; Playwright CLI iteration confirms rendering
6 Adversarial validation (opt-in) Probes pass or defects fixed and pinned by a regression test

Phase 0 — Preflight

Run these read-only checks before writing anything:

# 1. Storybook installed?
jq '.devDependencies | keys[]' package.json | grep -E '@storybook/'

# 2. Storybook config dir present?
ls .storybook/ 2>/dev/null

# 3. Platform — web (Vite / Next) or native (Expo / RN)? Check
#    dependencies, devDependencies, AND peerDependencies — shared
#    component libraries (`packages/ui`) consumed by an Expo app
#    declare `react-native` as a peer.
jq '(.dependencies // {}) + (.devDependencies // {}) + (.peerDependencies // {}) | keys[]' package.json | grep -E '^(react-native|expo|@storybook/react-native)'

Decision table:

State Action
Storybook installed + .storybook/ present Proceed to Phase 1.
Storybook missing Halt. Ask user to install Storybook before invoking this skill again.
react-native or expo in dependencies Set --platform native. Load rules/react-native.md.
Neither present Set --platform web.
--auth <profile> passed Load rules/auth.md. Resolve secret before Phase 5.

Phase 1 — Component inspection

Read the component file. Enumerate, in this order:

  1. The component's exported name.
  2. Each prop, its TypeScript type, and whether it is optional.
  3. Each visible state derivable from props (isLoading, error, disabled, variant, size).
  4. Each callback prop that an interaction test will need to spy on (onClick, onChange, onSubmit, …).
  5. Any context providers the component requires (theme, query client, router) — these go into the meta decorators.

Output the inventory inline before scaffolding. The user reads it and corrects misinterpretations before any file is written.

Phase 2 — Visual regression scaffold

Write <kebab-case-name>.stories.tsx next to the component file. Full rules and the variant-grouping pattern live in rules/create-stories.md.

The shape, in one diagram:

default export (Meta)
└── title: "<Inferred>/<ComponentName>"
└── component: <Component>
└── parameters: { layout: "padded" | "centered" | "fullscreen" }

export const Default: Story = {
  render: () => (
    <variants grouped — one Chromatic snapshot per file>
  ),
};

Use the literal scaffolding in:

If the repo already exports a Stories / Stories.Entry helper (checked by Grep "Stories\\.Entry" against the repo), use it to group variants into a single snapshot. Otherwise emit a plain flex/stack wrapper. The decision tree is in rules/create-stories.md.

Phase 3 — Playground scaffold

Append a Playground story to the same file. Every prop becomes an argTypes control. Mapping:

TypeScript prop argTypes control
boolean { control: "boolean" }
string { control: "text" }
number with inferable min/max { control: { type: "range", min: <n>, max: <n>, step: <n> } }
number without explicit clamps { control: "number" }
Union of string literals { control: "select", options: [...] }
Callback (onClick, onChange) args: { onClick: fn() } — imported from storybook/test
ReactNode / children { control: "text" } with a default string

Full example: see "Playground story" in rules/create-stories.md.

Phase 4 — Interaction test scaffold

Write <kebab-case-name>.test.stories.tsx next to the component file.

Hard rules (full reasoning in rules/interaction-tests.md):

  • File suffix is .test.stories.tsx. Do not use .interactions.stories.tsx, .spec.stories.tsx, or anything else.
  • Title is <same-prefix>/Tests. One Storybook namespace per file — CSF3 allows exactly one default export.
  • tags: ["test"] is set on the meta so the test runner picks it up.
  • parameters.chromatic = { disableSnapshot: true } keeps these stories out of visual regression.
  • All userEvent calls are awaited; all expect calls are awaited.
  • Locator priority: getByRole → getByLabelText → getByPlaceholderText → getByText → getByTestId. Never start with getByTestId.

Use the literal scaffolding in:

Phase 5 — Verification

Start Storybook in the background and iterate against the live URL. Full Playwright CLI loop in rules/playwright-cli.md.

Minimum verification, in this order:

  1. Story compiles — Storybook prints no error in the terminal.
  2. Story renders — Playwright CLI navigates to the story URL and the canvas root selector resolves.
  3. Default story is reachable from the sidebar at the inferred title.
  4. Interaction test passes via the Storybook test runner (e.g. npm run test-storybook) — if the runner is wired up.

For visual evidence (a screenshot or short clip of the rendered story), delegate to the pr-reviewer agent or the screen-recorder skill. Full handoff rules in rules/visual-verification.md.

If the Storybook URL is gated and --auth <profile> was passed, the Playwright CLI invocation reuses the storageState.json produced by the auth profile's login flow. The skill never types credentials into the Playwright CLI directly.

Phase 6 — Adversarial validation (opt-in, --validate)

Runs only when --validate is passed, or standalone via /storybook validate <component>. It is local and interactive — it drives Playwright against the running Storybook, so it never runs in CI.

Phase 5 proves the story renders. Phase 6 proves the component works, then tries to break it: hostile inputs, rapid and duplicate events, keyboard-only navigation, viewport extremes, and error states. Each defect is triaged as a story bug or a component bug, fixed behind a confidence gate, and pinned with a regression test.

The loop, in one line: probe → triage → fix (gated) → pin with a regression test → re-validate.

  • Same tool as Phase 5, not a second browser path. Probes run as a short Playwright script under .agent/storybook/.probe/ (gitignored) so they can capture console errors, page errors, and failed requests — the signals a bare screenshot misses.
  • Story bugs (bad args, missing decorator, wrong locator) are fixed in the story or test directly — no gate.
  • Component bugs (crash, unescaped input, handler firing while disabled, focus trap, overflow) are gated: score with confidence, apply only at ≥ 90, and report sub-90 findings for the user to decide. Every applied fix is pinned by a regression case in .test.stories.tsx.
  • Never swallow the error, delete a probe, or .skip a test to force a green run.

Full probe catalog, the harness pattern, triage rules, and the loop cap live in rules/adversarial-validation.md.


Decision flow at a glance

Signal Do
Component has no .stories.tsx Run the full workflow (Phases 0–5).
Component has .stories.tsx but no .test.stories.tsx Skip to Phase 4. Reuse the existing meta title for the /Tests peer.
--validate passed, or /storybook validate <component> Run Phase 6. Load rules/adversarial-validation.md. Local only.
Running in CI Skip Phase 6 — it drives a live browser and is not reproducible.
Repo has react-native or expo Set --platform native. Load rules/react-native.md.
Storybook URL is http://localhost:6006/... (or similar) Iterate via Playwright CLI. No auth needed.
Storybook URL is gated (login form, SSO, basic auth) Resolve --auth <profile> first. Load rules/auth.md.
Visual evidence requested in the PR Delegate to pr-reviewer or screen-recorder.
Component is a hook or non-visual Stop. Defer to tdd.
Storybook isn't installed Halt. Ask the user to install Storybook before re-running.

Composes with

  • tdd — owns unit / hook tests. This skill defers below the visual surface to it.
  • test-provenance-guard — run on the generated .test.stories.tsx to ensure the test imports production component code, not a private shim.
  • pr-reviewer — runs the visual check pass and posts screenshots on the PR (Critical / High motion findings, visual diffs).
  • screen-recorder — captures short videos of multi-frame interactions where a still screenshot cannot prove the change (transitions, focus order, hover-revealed UI).
  • ux — call after stories are scaffolded to audit the rendered states for accessibility and microcopy.
  • visual-design — call before scaffolding when the component is new and the visual direction is not yet committed (palette, type, signature details). Call after scaffolding in review mode if the rendered variants look generic or drift from the chosen direction. Pairs with ux — ux audits the floor, visual-design shapes the ceiling.
  • confidence — gate before declaring the scaffold done if the user disputes a generated variant.

Rules

  • rules/create-stories.md — visual regression *.stories.tsx pattern: grouped variants, Playground story, layout parameter, static mock data only.
  • rules/interaction-tests.md — *.test.stories.tsx hard requirements: /Tests namespace, awaited userEvent, locator ladder, fn() spies, step() grouping.
  • rules/react-native.md — Expo / React Native flavor: @storybook/react-native differences, native locators, mobile-only template paths.
  • rules/auth.md — opt-in per-pathname auth: config schema, OS-keychain commands, storageState reuse, multi-profile routing, secret rotation.
  • rules/playwright-cli.md — iteration loop against the running Storybook URL: snapshot mode, --last-failed, iframe routes, story permalinks, headed vs headless.
  • rules/adversarial-validation.md — opt-in Phase 6 (--validate): the probe harness, the adversarial catalog, story-vs-component triage, the confidence-gated fix path, and the loop cap.
  • rules/visual-verification.md — delegation rules for the pr-reviewer agent and screen-recorder skill, when each is the right tool.
  • rules/anti-patterns.md — full list of patterns to refuse.

References

  • references/platform-detection.md — how the skill decides web vs native, and the Storybook builder matrix per framework.
  • references/flake-cookbook.md — copy-paste decorator snippets for the five most common flake sources (animations, fonts, dates, random IDs, theme drift). Load only when an existing story has flaked or the user asks for deterministic snapshots — adding all five preemptively is cargo-culting.

Templates


Anti-patterns (one-liner — full list in rules/anti-patterns.md)

  • Mixing visual regression stories and interaction tests in the same file.
  • Naming interaction tests *.interactions.stories.tsx or *.spec.stories.tsx instead of *.test.stories.tsx.
  • Dynamic values (new Date(), Math.random()) in story args — guarantees Chromatic / Loki false positives.
  • Skipping the locator ladder and reaching straight for getByTestId.
  • Storing Storybook credentials in .env, package.json, or the story file itself.
  • Generating a Playground story whose argTypes do not match the component's actual prop types.
  • Running Playwright CLI in headed mode in CI.
  • Running --validate in CI — it drives a live browser and is not reproducible.
  • Under --validate, forcing a green run by swallowing the error, deleting a probe, or .skip-ing a test, or editing component source below a confidence of 90.

Definition of done

  • Phase 0 preflight passed; platform set; auth profile resolved if --auth was given.
  • <name>.stories.tsx written with a Default story (grouped variants) and a Playground story (unless --no-playground).
  • <name>.test.stories.tsx written under the /Tests namespace (unless --no-interactions).
  • Storybook compiles with no terminal errors.
  • Playwright CLI confirms the story URL renders.
  • Interaction test passes via the Storybook test runner (if the runner is wired up in the repo).
  • No credentials in the generated files.
  • If --auth <profile> was used, storageState.json is written under .agent/storybook/.auth/ and listed in .gitignore.
  • If --validate was used: applicable probes ran; findings triaged as story or component; component fixes applied only at confidence ≥ 90 and pinned by a regression test; sub-90 findings reported; the ephemeral probe script deleted and Storybook killed on exit.