Skip to content

UI changes ship a human-reviewable screenshot index

State: open/proposed

  • A UI change ships screenshots of every surface it touches, organized for a human first: grouped by surface or category, captioned, with before and after where a surface changed.
  • One static page indexes the set with a table of contents.
  • The same organization serves agents reviewing the change.

A PR that changes a UI surface ships all of the following:

  • (a) Captured screenshots. Taken by a repeatable driver — a gated Playwright spec or a Storybook capture — light and dark where the surface supports both, at a stated viewport.
  • (b) Committed images. Beside the surface’s own docs, at docs/screenshots/<set>/, named by surface and variant.
  • (c) A static index. An index.html beside the images with a left table of contents, one section per category, a caption per image, and before/after pairs where a surface changed.
  • (d) A PR body that embeds the evidence. The key screenshots, each with a caption and the decision the reviewer should react to, plus a link to the index.
  • (e) A current set. A stale committed screenshot is a defect. Regenerate the set for every surface the change touched.

A human reviews by looking. A PR of Vue or component diffs is not reviewable by a product owner, a designer, or anyone who does not read the framework’s markup for a living. Agents reviewing the same change need the same organized evidence, not a second format. Screenshots are the contract for whether a change matches the design; without them, “does it look right” has no answer until someone runs the app. See P-0016-understandable-by-humans.

  • Write the capture driver as a gated Playwright spec (CAPTURE_SHOTS=1 bunx playwright test ...) or a Storybook capture, following an existing driver’s conventions in the same product: the shell’s own theme toggle rather than color-scheme emulation, a settle pause before the shutter, a fixed viewport such as 1440x900 at 2x.
  • Commit the PNGs at docs/screenshots/<set>/, named by surface and variant — a <surface>-{light,dark}.png pair, or <surface>--<variant>.png for a captioned state.
  • Build index.html beside the screenshots: a left-hand table of contents grouped by category, one caption per image, before/after pairs shown together where a surface changed. No build step; it opens as a plain file.
  • In the PR body, embed the screenshots that matter most, each with a caption and the specific decision the reviewer should react to, and link the index page for the full set.
  • When a change touches a UI surface, regenerate every screenshot for that surface in the same PR — never update some and leave others stale.
  • Reviewers: a UI PR with no screenshot index, or with a screenshot older than the diff it documents, is incomplete. Ask for the set before approving.
  • A PR that changes a Vue component’s markup with no screenshots attached — the diff alone does not show what changed on screen.
  • A screenshot set where only some of the surfaces a shared-component change touched were recaptured.
  • Screenshots pasted into a PR body with no committed index — a later reviewer or an agent has no way to browse the full set.
  • A change with no visual effect — a refactor that renders identically — may cite the existing, unchanged screenshots instead of recapturing them.
  • A hotfix may ship before the index is regenerated, if the PR names the follow-up that will update it.
  • S-0010-design-language-consumption is the sibling standard for how a surface looks once it ships.

← Back to Standards