Test dark mode, themes, and viewports with modes
Capture a story in multiple viewports and themes with parameters.uiVerify.modes. Each mode gets its own baseline, and an existing Chromatic modes config carries over.
A mode is a capture variant of a story: a viewport and theme it should be screenshotted in. Declare modes on a story and UI Verify renders it once per mode, each diffed against its own per-mode baseline - so a single Button story can cover mobile light, desktop dark, and everything between, without a separate story for each.
Declare modes on a story
Set parameters.uiVerify.modes to an object keyed by mode name, each entry giving a viewport and/or a theme. UI Verify reads the same shape under parameters.chromatic, the drop-in Chromatic-compatible namespace, so an existing Chromatic config carries over unchanged. Set it on a single story, or on the component meta to cover the whole file.
export default {
component: Button,
parameters: {
uiVerify: {
modes: {
"Mobile light": { viewport: "small", theme: "light" },
"Desktop dark": { viewport: "large", theme: "dark" },
},
},
},
};A mode's viewport is a named viewport from your Storybook viewport options. For plain widths with no theme, the legacy viewports array still works - parameters.uiVerify.viewports: [320, 768, 1280] renders the story at each pixel width.
Each mode is its own baseline
A story rendered in three modes produces three screenshots, each with its own per-branch baseline, so accepting a dark-mode change never touches the light-mode baseline. Modes also multiply your snapshot count - three modes is three billable snapshots - so declare the ones that matter and lean on dense stories to keep the total down.
How is a theme applied?
A mode's theme value is set as the theme:<value> Storybook global for that capture, and light/dark also emulate the OS color scheme (prefers-color-scheme). Your Storybook has to respond to that global - usually through your existing theme decorator or addon - exactly as it does under Chromatic.
Do my Chromatic modes carry over?
Yes. UI Verify reads both parameters.uiVerify.modes and the Chromatic-compatible parameters.chromatic.modes (plus the legacy viewports width array), and uiVerify wins per key when a story sets both - so an existing Chromatic modes config renders the same variants with no change. A mode set to { disable: true } opts a story out of a mode it would otherwise inherit.
Visual testing for agents
UI Verify captures your UI on every pull request and an AI judge tells an intended change from a real regression. See how it works.
Get started