responsive-breakpoint-runner
Produces a single breakpoint-matrix report (rows = pages/stories, columns = viewports) across Percy, Chromatic, Playwright snapshots, or Storybook test-runner. Routes per-engine viewport syntax, runs each, and aggregates the results into one cross-breakpoint view. Use when the team needs one unified pass/fail view across three or more viewport widths instead of separate per-engine or per-breakpoint reports. The matrix-view output is the distinguishing trait: it dispatches to playwright-snapshots (and the other engines) rather than replacing any single-engine skill.
responsive-breakpoint-runner
Overview
Most teams need to assert a UI across multiple breakpoints (mobile, tablet, desktop, sometimes wide-desktop). The four engines covered in this plugin each have their own way to express a viewport list:
This skill is a dispatcher: pick the engine the project already runs, follow the matching pattern below, then aggregate into a single breakpoint report. It does not replace any engine - it composes the plugin's per-engine skills.
When to use
If the project only covers a single breakpoint, defer this skill - go directly to the relevant per-engine SKILL.md.
Dispatcher: pick by engine
Is the project using Chromatic + Storybook?
├── Yes → follow "Chromatic dispatch" below.
└── No
├── Is the project using Percy?
│ └── Yes → follow "Percy dispatch" below.
└── No
├── Is the project using @storybook/test-runner without Chromatic?
│ └── Yes → follow "Storybook test-runner dispatch" below.
└── No (project uses raw @playwright/test snapshots)
└── follow "Playwright dispatch" below.If the project uses two engines (e.g. Chromatic for stories + Playwright snapshots for full pages), apply the matching pattern to each independently and use the visual-baseline-gate skill to aggregate verdicts.
Chromatic dispatch
Per the Chromatic viewports docs, viewports are configured per story via parameters.chromatic.viewports. Pixel widths, set inside the story's parameters block:
// Header.stories.ts
export default {
title: 'Components/Header',
component: Header,
parameters: {
chromatic: {
viewports: [375, 768, 1280, 1920],
},
},
};A story with multiple viewports produces one snapshot per viewport in the same Chromatic build. Pair with TurboSnap (--only-changed, see chromatic-visual-regression-testing) so a per-PR breakpoint matrix doesn't blow up snapshot quota.
Percy dispatch
Per Percy CLI, project-wide widths are set in the Percy config file (.percy.yml, percy.config.js, etc., resolved per the order documented in percy-visual-regression-testing):
# .percy.yml
version: 2
snapshot:
widths: [375, 768, 1280, 1920]
min-height: 1024For a single overridden snapshot, pass the widths in the SDK call:
await percySnapshot(page, 'Homepage', { widths: [375, 1280] });(Per the per-engine readme - when in doubt, check the latest percy/cli release for the current snapshot config schema.)
Playwright dispatch
Per playwright-snapshots, the canonical pattern is one project per breakpoint, each with its own viewport set:
// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
projects: [
{ name: 'mobile-375', use: { ...devices['Desktop Chrome'], viewport: { width: 375, height: 667 } } },
{ name: 'tablet-768', use: { ...devices['Desktop Chrome'], viewport: { width: 768, height: 1024 } } },
{ name: 'desktop-1280',use: { ...devices['Desktop Chrome'], viewport: { width: 1280, height: 800 } } },
{ name: 'wide-1920', use: { ...devices['Desktop Chrome'], viewport: { width: 1920, height: 1080 } } },
],
});Run the matrix:
npx playwright test --project=mobile-375
npx playwright test --project=tablet-768
npx playwright test # runs all projects in parallelEach project produces its own snapshot suffix (-chromium-linux-mobile-375.png etc.) so baselines are isolated. See playwright-snapshots for the naming convention.
Storybook test-runner dispatch
When using @storybook/test-runner without Chromatic, drive the viewport via the test-runner's preVisit hook (per storybook-test-runner):
// .storybook/test-runner.ts
import type { TestRunnerConfig } from '@storybook/test-runner';
import { expect } from '@playwright/test';
const VIEWPORTS = [375, 768, 1280, 1920];
const config: TestRunnerConfig = {
async postVisit(page, context) {
for (const width of VIEWPORTS) {
await page.setViewportSize({ width, height: Math.round(width * 0.75) });
await expect(page.locator('#storybook-root')).toHaveScreenshot(
`${context.id}-${width}.png`
);
}
},
};
export default config;Note this pattern multiplies snapshot count by VIEWPORTS.length - acceptable for a few hundred stories; reconsider above ~1000 stories where Chromatic's TurboSnap makes more economic sense.
Producing the unified report
Every per-engine run can produce a per-breakpoint pass/fail line. To build a single "what broke at which breakpoint" view, normalize each engine's output to a row shape:
{
"engine": "playwright",
"breakpoint": "mobile-375",
"story_or_url": "/dashboard",
"status": "fail",
"diff_pixels": 1234,
"diff_url": "playwright-report/data/dashboard-mobile-375-diff.png"
}Then render a markdown matrix (rows = pages/stories, columns = breakpoints):
| Page / Story | mobile-375 | tablet-768 | desktop-1280 | wide-1920 |
|-------------------------|:----------:|:----------:|:------------:|:---------:|
| /dashboard | ❌ | ✅ | ✅ | ✅ |
| /onboarding | ✅ | ✅ | ✅ | ✅ |
| /pricing | ✅ | ❌ | ❌ | ✅ |A single failed cell tells the reviewer which breakpoint broke, which is the entire reason this skill exists. Pipe the matrix into $GITHUB_STEP_SUMMARY (or the GitLab / Jenkins equivalent) for a clickable PR-side summary.
For a hard CI gate that fails on any cell, use visual-baseline-gate - it accepts this row shape directly.
CI integration
The CI workflow follows whichever per-engine SKILL.md you dispatched to; the only added concern is uploading every breakpoint's report artifact (Playwright HTML report, Chromatic build URL, Percy build URL) so a reviewer can see the diff for a specific cell:
- name: Upload all visual artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: visual-reports-all-breakpoints
path: |
playwright-report/
test-results/
.chromatic/
.percy/
retention-days: 14