Author economical visual tests β full visual coverage in the fewest billable snapshots...
Every per-snapshot visual tool β UI Verify, Chromatic, Percy, Playwright screenshots β renders and bills per story. So the number of stories is the cost and the noise surface. The naive pattern (one story per variant Γ state Γ theme) multiplies both fast: a component with 5 sizes Γ 3 states Γ 2 themes is 30 snapshots the naive way. This skill collapses that to a handful while keeping full coverage.
The technique is tool-agnostic; the payoff (fewer billed shots, fewer places to flake) is the same everywhere.
Render the whole matrix together in a single story: a grid of every size/state side by side. One snapshot then covers the entire matrix.
// Button.stories.tsx β ONE story covers every size Γ variant
export const AllVariants = () => (
<div style={{ display: 'grid', gap: 16, gridTemplateColumns: 'repeat(3, max-content)' }}>
{(['sm', 'md', 'lg'] as const).flatMap((size) =>
(['primary', 'secondary', 'danger'] as const).map((variant) => (
<Button key={`${size}-${variant}`} size={size} variant={variant}>
{size}/{variant}
</Button>
)),
)}
</div>
);
9 buttons, 1 snapshot instead of 9.
For a component that normally fetches, don't write a story per response state. Render each state from a fixed fixture β a table of props/mock-responses β in one story. Deterministic input in, deterministic pixels out, many states, few shots.
const CASES = [
{ label: 'empty', items: [] },
{ label: 'one', items: [fixtures.one] },
{ label: 'many', items: fixtures.many },
{ label: 'error', error: 'Failed to load' },
];
export const AllStates = () => (
<div style={{ display: 'grid', gap: 24 }}>
{CASES.map((c) => (
<section key={c.label}>
<h4>{c.label}</h4>
<List items={c.items} error={c.error} />
</section>
))}
</div>
);
(If the component fetches internally rather than taking props, mock the request instead β see
storybook-visual-testing, "mock data." The point is the same: fixtures, not N stories.)
Consolidating into one snapshot is coarser granularity: a diff anywhere in the gallery flags the whole story, and you lose the per-variant baseline/accept. So this is a balance, not "merge everything":
When you refactor, state the delta so the value is legible:
This collapses 28 stories β 2 snapshots (the sizeΓvariantΓtheme matrix into one gallery, the four data states into one story). ~93% fewer billed shots, same coverage.
Loading, Empty, Error, Loaded as four stories) β one
data-driven story (move 2).