Skip to content

Storybook

If your components have Storybook stories, facetshot can take screenshots of every story on every device and variant, without any setup per story. Storybook 7 to 10 are supported.

Tell facetshot where your Storybook is: one you run yourself, or a static build that facetshot makes and serves:

storybook: { url: 'http://localhost:6006' }
storybook: {
build: {
cmd: 'bunx --bun storybook build -o storybook-static',
inputs: ['src', '.storybook', 'package.json'],
output: 'storybook-static'
}
}

As with web builds, the static build only runs again when one of its inputs has changed.

facetshot story:button--primary # one story, by id
facetshot story:Button # every story of a component
facetshot story:Forms # every story in a folder of components
facetshot 'story:Button/*' # a glob over titles and names
facetshot 'story:*' --on phone,desktop # everything

Matching ignores case. Each story becomes a screen of its own in the results (Button.Primary), with its own contact sheet.

Docs pages are left out, and so are stories you’ve opted out of tests: tagged !test (Storybook 8.1+) or facetshot-skip. A story you name exactly is always taken, whatever its tags.

facetshot waits for Storybook to finish preparing, loading, rendering and running the story’s play function, and for the story to have drawn something, and then applies the usual readiness rules. Rules for stories go under storybook.ready; keys under routes match story ids:

storybook: {
ready: { gone: ['.loading'], routes: { 'chart--*': { timeout: 30000 } } }
}

A story can carry its own settings in its parameters:

export const Live: Story = {
parameters: { facetshot: { skip: true } } // never taken
};
export const Chart: Story = {
parameters: { facetshot: { ready: { visible: ['svg'] }, mask: ['.timestamp'] } }
};

If Storybook shows an error for a story, it is reported as a finding on that screenshot.

Light and dark, contrast, reduced motion and print come from the browser, as on any web page. If your Storybook switches themes with a toolbar global instead of following the browser, map variants to globals:

storybook: {
globals: { light: 'theme:light', dark: 'theme:dark', locale: 'locale:{locale}' }
}

Keys are variant names (or locale, for any variant with a locale); values are key:value pairs, joined with ;.