chromatic
Automates visual regression testing for Storybook components using cloud-based snapshot comparison. Use when setting up visual testing, catching UI regressions, or reviewing component changes.
Installation
Follow the repository instructions for this skill and your agent. Review the files and dependencies before adding it to your workflow.
View source ↗GuidesSkill instructions
Chromatic Visual Testing
Cloud-based visual testing platform that captures screenshots of every Storybook story and detects visual changes.
Quick Start
# Install Chromatic
npx storybook add chromatic
# Or install manually
npm install --save-dev chromatic
# Run visual tests (first time creates baselines)
npx chromatic --project-token=<token>
How It Works
- Cloud Rendering: Chromatic renders components in cloud browsers
- Snapshot Capture: Takes screenshot of each story
- Automated Diffing: Compares new snapshots to baselines
- Review & Verify: Approve or reject visual changes
Configuration
chromatic.config.json
{
"projectToken": "chpt_xxxxxxxxxxxx",
"buildScriptName": "build-storybook",
"storybookBuildDir": "storybook-static",
"zip": true,
"autoAcceptChanges": "main",
"exitOnceUploaded": false,
"exitZeroOnChanges": false,
"onlyChanged": true,
"externals": ["public/**"],
"skip": "dependabot/**"
}
Package.json Scripts
{
"scripts": {
"chromatic": "chromatic --exit-zero-on-changes",
"chromatic:ci": "chromatic --auto-accept-changes=main"
}
}
Story-Level Configuration
Disable Snapshots
// Skip specific story
export const Loading: Story = {
parameters: {
chromatic: { disableSnapshot: true }
}
};
// Skip all stories in file
export default {
title: 'Components/Spinner',
parameters: {
chromatic: { disableSnapshot: true }
}
};
Viewport Testing
export const Responsive: Story = {
parameters: {
chromatic: {
viewports: [320, 768, 1200]
}
}
};
Delay for Animations
export const Animated: Story = {
parameters: {
chromatic: {
delay: 300, // Wait 300ms before snapshot
pauseAnimationAtEnd: true
}
}
};
Diff Threshold
export const SubtleChanges: Story = {
parameters: {
chromatic: {
diffThreshold: 0.2 // 0-1, higher = more tolerant
}
}
};
Multi-Browser Testing
// Test in multiple browsers
export default {
title: 'Components/Button',
parameters: {
chromatic: {
modes: {
chrome: { viewport: 1200 },
firefox: { viewport: 1200 },
safari: { viewport: 1200 },
edge: { viewport: 1200 }
}
}
}
};
Modes for Theme/Locale Testing
// .storybook/modes.ts
export const allModes = {
light: { theme: 'light' },
dark: { theme: 'dark' },
mobile: { viewport: { width: 375, height: 667 } },
desktop: { viewport: { width: 1200, height: 800 } }
};
// Component story
export const Button: Story = {
parameters: {
chromatic: {
modes: {
'light desktop': allModes['light'],
'dark desktop': { ...allModes['dark'], ...allModes['desktop'] },
'light mobile': { ...allModes['light'], ...allModes['mobile'] }
}
}
}
};
CI Integration
GitHub Actions
name: Chromatic
on: push
jobs:
chromatic:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Required for accurate baselines
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- uses: chromaui/action@latest
with:
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
autoAcceptChanges: main
onlyChanged: true
GitLab CI
chromatic:
stage: test
image: node:20
script:
- npm ci
- npx chromatic --project-token=$CHROMATIC_PROJECT_TOKEN
only:
- merge_requests
- main
TurboSnap (Incremental Testing)
Only test stories affected by code changes:
npx chromatic --only-changed
Configure in CI:
- uses: chromaui/action@latest
with:
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
onlyChanged: true
traceChanged: expanded # Track changes across files
Handling Dynamic Content
Ignore DOM Elements
export const WithTimestamp: Story = {
parameters: {
chromatic: {
diffIncludeAntiAliasing: false
}
},
decorators: [
(Story) => (
<>
<Story />
<span data-chromatic="ignore">
{new Date().toISOString()}
</span>
</>
)
]
};
Mock Data
export const UserProfile: Story = {
parameters: {
chromatic: { delay: 500 }
},
loaders: [
async () => ({
user: { name: 'Test User', avatar: '/mock-avatar.png' }
})
]
};
Review Workflow
Accept Changes
# Auto-accept on main branch
npx chromatic --auto-accept-changes=main
# Accept specific branches
npx chromatic --auto-accept-changes="main|release/*"
Skip Builds
# Skip CI for specific patterns
npx chromatic --skip="dependabot/**"
# Skip with commit message
git commit -m "docs: update readme [skip chromatic]"
Troubleshooting
Flaky Tests
// Increase delay for async content
parameters: {
chromatic: {
delay: 1000,
diffThreshold: 0.1
}
}
Font Loading Issues
// Wait for fonts in preview.js
export const decorators = [
(Story) => {
const [fontsLoaded, setFontsLoaded] = useState(false);
useEffect(() => {
document.fonts.ready.then(() => setFontsLoaded(true));
}, []);
return fontsLoaded ? <Story /> : null;
}
];
External Resources
{
"externals": [
"public/fonts/**",
"public/images/**"
]
}
See references/configuration.md for complete CLI options and references/ci-integration.md for advanced CI setups.
Examples
Read the usage examples in the source repository.
View source ↗Source history
- Indexed on
- 2026-01-20
- Index updated
- 2026-01-28
- Branch
- main
Index and sync dates describe this directory. View the source repository for code history.
GitHub ↗chat Comments (0)
Sign in to join the discussion and leave a comment.
No comments yet. Be the first to share your thoughts!