Storybook GitHub Action
The pxdiff/storybook GitHub Action uploads a Storybook build, discovers stories, captures screenshots, and diffs them against baselines — all in one step.
Quick Start
Section titled “Quick Start”name: Visual Regressionon: pull_request
jobs: visual: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- name: Build Storybook run: npm run build-storybook
- name: pxdiff Visual Regression uses: pxdiff/storybook@v1 with: api-key: ${{ secrets.PXDIFF_API_KEY }} build-dir: ./storybook-staticInputs
Section titled “Inputs”| Input | Required | Default | Description |
|---|---|---|---|
api-key | yes | pxdiff API key | |
build-dir | yes | Path to the Storybook build directory | |
suite | no | "default" | Suite name for grouping snapshots |
auto-baseline | no | "false" | Set baselines from captured screenshots (no diff) |
auto-approve | no | "false" | Run diff and automatically approve all changes and set baselines |
threshold | no | Diff threshold 0.0–1.0 | |
filter | no | Glob pattern to filter stories | |
only-changed | no | "false" | Only capture stories affected by code changes (change detection) |
api-url | no | "https://pxdiff.com" | pxdiff API URL |
cli-version | no | (set at publish) | @pxdiff/cli version range to install |
Outputs
Section titled “Outputs”| Output | Description |
|---|---|
diff-url | URL to the diff review page |
status | "passed" or "failed" |
changed | Number of changed snapshots |
new | Number of new snapshots |
capture-id | Capture ID |
diff-id | Diff ID |
Examples
Section titled “Examples”Basic Storybook
Section titled “Basic Storybook”- name: pxdiff uses: pxdiff/storybook@v1 with: api-key: ${{ secrets.PXDIFF_API_KEY }} build-dir: ./storybook-staticWith Suite and Filtering
Section titled “With Suite and Filtering”- name: pxdiff uses: pxdiff/storybook@v1 with: api-key: ${{ secrets.PXDIFF_API_KEY }} build-dir: ./storybook-static suite: design-system filter: "Button*" threshold: "0.1"Change Detection
Section titled “Change Detection”Only capture stories affected by code changes. Requires building Storybook with --stats-json:
- name: Build Storybook run: npm run build-storybook -- --stats-json
- name: pxdiff uses: pxdiff/storybook@v1 with: api-key: ${{ secrets.PXDIFF_API_KEY }} build-dir: ./storybook-static only-changed: trueSee the Storybook guide for details on how change detection works.
Auto-Baseline on Main
Section titled “Auto-Baseline on Main”Use auto-baseline to set baselines from captured screenshots without diffing. Useful for initial setup or on merge to the default branch:
- name: pxdiff uses: pxdiff/storybook@v1 with: api-key: ${{ secrets.PXDIFF_API_KEY }} build-dir: ./storybook-static auto-baseline: "true"Auto-Approve on Main
Section titled “Auto-Approve on Main”Use auto-approve to run the diff and automatically approve all changes, setting new baselines. Unlike auto-baseline, this still creates a diff so you can see what changed:
- name: pxdiff uses: pxdiff/storybook@v1 with: api-key: ${{ secrets.PXDIFF_API_KEY }} build-dir: ./storybook-static auto-approve: "true"Comment PR on Changes
Section titled “Comment PR on Changes”- name: pxdiff id: pxdiff uses: pxdiff/storybook@v1 with: api-key: ${{ secrets.PXDIFF_API_KEY }} build-dir: ./storybook-static
- name: Comment on PR if: steps.pxdiff.outputs.changed != '0' || steps.pxdiff.outputs.new != '0' uses: actions/github-script@v7 with: script: | github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: `**pxdiff:** ${steps.pxdiff.outputs.changed} changed, ${steps.pxdiff.outputs.new} new snapshots.\n\n[Review diff](${steps.pxdiff.outputs.diff-url})` })Full Workflow
Section titled “Full Workflow”A complete workflow that builds Storybook, runs visual regression, and requires approval:
name: Visual Regressionon: pull_request
jobs: visual: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- uses: actions/setup-node@v4 with: node-version: 24 cache: npm
- run: npm ci - run: npm run build-storybook
- name: pxdiff Visual Regression id: pxdiff uses: pxdiff/storybook@v1 with: api-key: ${{ secrets.PXDIFF_API_KEY }} build-dir: ./storybook-static suite: storybookHow It Works
Section titled “How It Works”The action runs these steps:
- Install CLI — installs
@pxdiff/cliglobally (skipped if already available) - Upload & Capture — runs
pxdiff storybook <source>which uploads the Storybook build, discovers stories, and captures screenshots - Diff — runs
pxdiff diffto compare against baselines (skipped whenauto-baselineistrue; runs with--auto-approvewhenauto-approveistrue) - Report — parses JSON output and sets GitHub Actions outputs
The action automatically detects the branch and commit from the GitHub Actions environment. No additional git configuration is needed.
Storybook Parameters
Section titled “Storybook Parameters”pxdiff reads Storybook parameters to control capture behavior. Set these in your stories:
export default { title: "Components/Button", parameters: { pxdiff: { delay: 500, // Wait 500ms before capture modes: { // Capture multiple modes mobile: { viewport: { width: 375, height: 812 } }, desktop: { viewport: { width: 1280, height: 720 } }, }, selector: ".button-wrapper", // Capture specific element cropToViewport: true, // Crop to viewport bounds ignoreSelectors: [".timestamp"], // Hide dynamic elements diffThreshold: 0.1, // Per-story threshold disable: false, // Set true to skip this story }, },};Legacy Viewports
Section titled “Legacy Viewports”If you’re using the viewports parameter instead of modes, pxdiff generates one target per viewport width:
parameters: { pxdiff: { viewports: [375, 768, 1280], // One capture per width },}modes is preferred over viewports as it supports arbitrary configuration beyond just width.