Storybook plugin for Vizzly - seamlessly integrate Storybook stories into your visual development workflow
npm install @vizzly-testing/storybookSeamlessly integrate your Storybook stories into Vizzly's visual development workflow. Iterate
locally with vizzly tdd, automatically create team builds from CI/CD, and collaborate on visual
changes with position-based comments and review rules.
``bash`
npm install @vizzly-testing/storybook
The plugin is automatically discovered by the Vizzly CLI via the @vizzly-testing/* scope.
`bashCapture screenshots from a static Storybook build
vizzly storybook ./storybook-static
$3
`javascript
import { run } from '@vizzly-testing/storybook';await run('./storybook-static', {
viewports: 'mobile:375x667,desktop:1920x1080',
concurrency: 3,
}, {
logger: console,
});
`Configuration
$3
Add a
storybook section to your vizzly.config.js file:`javascript
// vizzly.config.js
export default {
storybook: {
viewports: [
{ name: 'mobile', width: 375, height: 667 },
{ name: 'tablet', width: 768, height: 1024 },
{ name: 'desktop', width: 1920, height: 1080 },
], browser: {
headless: true,
args: ['--no-sandbox'],
},
screenshot: {
fullPage: false,
omitBackground: false,
},
concurrency: 3,
include: 'components/**',
exclude: '*/.test',
interactions: {
// Pattern-based hooks
'Button/*': async (page) => {
await page.hover('button');
},
'Tooltip/*': async (page) => {
await page.click('.tooltip-trigger');
},
},
},
};
`Run
vizzly init to generate a config file with sensible defaults.$3
You can configure specific stories by adding a
vizzly parameter in your story files:`javascript
// Button.stories.js
export let Primary = {
args: { label: 'Click me' },
parameters: {
vizzly: {
viewports: [
{ name: 'mobile', width: 375, height: 667 },
],
beforeScreenshot: async (page) => {
await page.hover('button');
},
},
},
};export let Disabled = {
args: { label: 'Disabled', disabled: true },
parameters: {
vizzly: {
skip: true, // Don't screenshot this story
},
},
};
`Configuration Priority
Configuration is merged in this order (later overrides earlier):
1. Default configuration (from plugin's
configSchema)
2. Config file (storybook key in vizzly.config.js)
3. CLI options
4. Per-story parametersCLI Options
-
--viewports - Comma-separated viewport definitions (format: name:WxH)
- --concurrency - Number of parallel stories to process (default: 3)
- --include - Include story pattern (glob)
- --exclude - Exclude story pattern (glob)
- --config - Path to custom config file
- --browser-args - Additional Puppeteer browser arguments
- --headless - Run browser in headless mode (default: true)
- --full-page - Capture full page screenshots (default: false)Interaction Hooks
Interaction hooks allow you to interact with stories before capturing screenshots.
$3
`javascript
// vizzly.config.js
export default {
storybook: {
interactions: {
'Button/*': async (page) => {
// Apply to all Button stories
await page.hover('button');
},
'Form/*': async (page) => {
// Apply to all Form stories
await page.fill('input[name="email"]', 'test@example.com');
await page.click('button[type="submit"]');
},
'Dropdown/WithOptions': async (page) => {
// Specific story
await page.click('.dropdown-toggle');
},
},
},
};
`$3
`javascript
export let WithTooltip = {
parameters: {
vizzly: {
beforeScreenshot: async (page) => {
await page.hover('.info-icon');
await page.waitForSelector('.tooltip', { visible: true });
},
},
},
};
`Pattern Matching
Patterns support glob-like syntax:
-
* - Match any characters except /
- ** - Match any characters including /
- Button/* - Match all Button stories
- components/** - Match all stories under components
- */.deprecated - Match all deprecated storiesScreenshot Naming
Screenshots are named using the format:
`
ComponentName/StoryName@viewportName
`Examples:
-
Button/Primary@mobile
- Card/WithImage@desktop
- Components/Atoms/Input/Default@tabletVisual Development Workflow
This plugin integrates Storybook into Vizzly's visual development workflow, enabling both local TDD
iteration and seamless team collaboration. The plugin automatically detects which mode to use:
$3
When a TDD server is running, screenshots are compared locally for fast iteration:
`bash
Start TDD server
vizzly tdd startCapture Storybook screenshots (automatically uses TDD mode)
vizzly storybook ./storybook-staticView live results at http://localhost:47392
`Output:
`
ā¹ š TDD mode: Using local server
ā¹ š Found 5 stories in ./storybook-static
ā¹ ā Components/Button/Primary@default
ā¹ ā
Captured 5 screenshots successfully
`$3
When a
VIZZLY_TOKEN is set, screenshots are uploaded to the cloud for team review:`bash
Capture and upload to Vizzly cloud (automatically uses Run mode)
VIZZLY_TOKEN=your-token vizzly storybook ./storybook-static
`Output:
`
ā¹ āļø Run mode: Uploading to cloud
ā¹ š https://app.vizzly.dev/your-org/project/builds/...
ā¹ š Found 5 stories in ./storybook-static
ā¹ ā Components/Button/Primary@default
ā¹ ā
Captured 5 screenshots successfully
ā¹ š View results: https://app.vizzly.dev/your-org/project/builds/...
`$3
The plugin automatically chooses the mode:
1. TDD mode - If a TDD server is running (
.vizzly/server.json found)
2. Run mode - If VIZZLY_TOKEN environment variable is set
3. Warning - If neither is available, warns and skips screenshotsNo need to wrap with
vizzly run - the plugin handles everything!Supported Storybook Versions
- Storybook v6.x
- Storybook v7.x
- Storybook v8.x
Example Workflow
1. Build your Storybook:
`bash
npm run build-storybook
`2. Capture screenshots with Vizzly:
`bash
vizzly storybook ./storybook-static
`3. Review in the Vizzly dashboard
Troubleshooting
$3
Ensure your Storybook build has an
index.json file:
`bash
ls storybook-static/index.json
`$3
Try adding browser arguments:
`bash
vizzly storybook ./storybook-static --browser-args "--no-sandbox,--disable-dev-shm-usage"
`$3
If your component needs time to render, wait for specific elements from your component to appear:
`javascript
interactions: {
'**': async (page) => {
// Wait for your component's content to be visible
await page.waitForSelector('.your-component-class', { visible: true });
},
}
``MIT Ā© Stubborn Mule Software