DEV Community

Sherotree
Sherotree

Posted on

Split AI-generated Storybook stories into one interaction each

I used to ask the agent for “Storybook coverage for this component.” It came back with one mega-story: default, hover, focus, error, loading, disabled, and a knobs panel that looked impressive and tested almost nothing.

Reviewers clicked the Control panel once, shrugged, and merged. Then Playwright started failing on the empty state we never actually rendered as its own story.

Now I force a boring rule: one interaction (or one meaningful state) per story. The agent can still generate many stories — just not one blob that pretends to be coverage.

What “one interaction” means

Not “one prop.” One thing a human would verify in isolation:

  • Default — happy path, no extras
  • Empty — zero items / blank slate
  • Loading — skeleton or spinner only
  • Error — recoverable failure message
  • Disabled — cannot activate
  • KeyboardFocus — focus ring visible without hover
  • WithLongLabel — truncation / wrap edge

Hover-only variants are fine as separate stories when hover changes layout or reveals controls. Don’t bury them behind a state select in Controls.

Why agents invent mega-stories

Models optimize for “looks complete.” One file with every arg mapped to a Control feels thorough. It’s also:

  • hard to screenshot for visual regression (which state is the baseline?)
  • easy to miss in review (you never open every Control combination)
  • useless as a failing repro — “open the story and toggle Error” is not a stable handoff

A failing Storybook story should be a URL + a story name, not a checklist of knobs.

Prompt I paste now

Add Storybook stories for `ShippingForm` in `ShippingForm.stories.tsx` only.

Rules:
- One story export per meaningful state/interaction (Default, Empty, Error, Loading, Disabled, KeyboardFocus).
- No mega-story with a `state` enum Control that switches everything.
- Prefer `args` / `render` per story over nested conditionals in one template.
- Each story must render without touching Controls.
- Max ~120 lines for the stories file. No new addons.
- Do not invent props the component doesn’t have — grep the component first.
Enter fullscreen mode Exit fullscreen mode

If the component truly needs a Control (theme, locale), I allow one shared Control at the meta level — not a state machine per story.

What I reject in review

Reject / ask to split

  • Single Playground story that covers empty + error + loading via Controls
  • render with a giant switch (args.variant) that duplicates the component’s own branches
  • Stories that only work after the reviewer toggles three knobs
  • “AllStates” grids that pack six UIs into one canvas (fine as a docs appendix, not as the only coverage)

Accept

  • Small, boring named stories
  • play functions that assert one interaction (tab to submit, see error text) on that story alone
  • Reused decorators for providers — shared setup is fine; shared “all states” is not

Visual regression loves this

Chromatic / Playwright story shots become obvious:

  • ShippingForm--Empty.png
  • ShippingForm--Error.png

When the agent “fixes” empty-state copy, the Empty shot moves. When it only tweaked the happy path, Default moves. Mega-stories hide which branch changed.

Tiny habit

Next time an agent ships a Playground story with twelve Controls, don’t argue taste in the PR thread. Leave a comment: split into named stories, one interaction each, same args — then paste the prompt above into the follow-up.

You’re not asking for more Storybook. You’re asking for stories that can fail out loud.

Top comments (0)