Component Screenshot
This skill captures component screenshots from Storybook Story files.
Workflow
1. Read the Story File
Read the Story file path provided by the user and extract:
- The
titlefield from the meta object - Exported Story names, such as
DefaultandWithIcon
2. Convert to a Story ID
Generate the Story ID used internally by Storybook.
Conversion rules:
- Convert the
titlevalue to lowercase. - Replace
/with-. - Append the export name in kebab-case, separated by
--.
Conversion examples:
| title | export | Story ID |
|---|---|---|
Screenshots/Shared/Card | Default | screenshots-shared-card--default |
Screenshots/Features/FilterBar/FilterList | Default | screenshots-features-filterbar-filterlist--default |
Screenshots/Shared/Button | WithIcon | screenshots-shared-button--with-icon |
Detailed conversion:
title: "Screenshots/Shared/Card" + export: "Default"
-> lowercase: "screenshots/shared/card"
-> `/` to `-`: "screenshots-shared-card"
-> + "--" + kebab(export): "screenshots-shared-card--default"
Convert PascalCase exports to kebab-case:
Default→defaultWithIcon→with-iconMSWExample→msw-example
3. Determine the Viewport Size
Choose the viewport size in this priority order:
- User override: when the user explicitly provides a size
- Story wrapper hint: the
style={{ width: '...', height: '...' }}value on the wrapper div insiderender - Default: width=1280, height=800
4. Run the Capture
Run ${SKILL_DIR}/scripts/capture-screenshot.ts to capture the screenshot.
The script serves a statically built Storybook (.dist/) through Express and captures from that server. Static files do not open an HMR websocket, so networkidle works reliably.
pnpm exec tsx ${SKILL_DIR}/scripts/capture-screenshot.ts \
--story-id "{story-id}" \
--output "artifacts/screenshots/{ComponentName}.png" \
--width {width} --height {height}
Script CLI options:
| Option | Required | Default | Description |
|---|---|---|---|
--story-id | ✅ | - | Storybook story ID |
--output | ✅ | - | Output PNG file path |
--width | ❌ | 1280 | Viewport width |
--height | ❌ | 800 | Viewport height |
--port | ❌ | 6008 | Static server port |
--timeout | ❌ | 30000 | Timeout in ms |
--rebuild | ❌ | false | Ignore the existing build and rebuild |
- If
.dist/iframe.htmlis missing, the script automatically runspnpm build-storybook. - If
--rebuildis passed, the script ignores the existing build and always rebuilds. - After navigation, it captures the first child under
#storybook-root > *.
5. Validate the Result
After capture, confirm:
- The PNG file was created
- The file size is greater than 0 to catch empty screenshots
- The final file path is reported back to the user
Error Handling
| Situation | Response |
|---|---|
| Story file missing | Stop and ask the user to verify the file path |
Failed to parse title | Ask the user to verify the Story file format |
| Storybook build failure | Suggest running pnpm build-storybook manually to inspect the error |
| Empty screenshot (0 bytes) | Suggest checking the Story ID directly in the browser after serving the static build at http://localhost:6006/iframe.html?id={story-id}&viewMode=story |
| Capture script error | Surface the error message and show the manual command |
Examples
Input
/screenshot __screenshots__/Card.stories.tsx
Execution
- Read
__screenshots__/Card.stories.tsx - Extract
title: Screenshots/Shared/Cardandexport: Default - Generate Story ID
screenshots-shared-card--default - Resolve the viewport: width=384 from the wrapper div, height=800 default
- Run:
pnpm exec tsx ${SKILL_DIR}/scripts/capture-screenshot.ts \ --story-id "screenshots-shared-card--default" \ --output "artifacts/screenshots/Card.png" \ --width 384 --height 800 - Confirm that
artifacts/screenshots/Card.pngwas created
When Multiple Story Exports Exist
If the Story file has multiple exports, ask the user which Story to capture.
/screenshot __screenshots__/Button.stories.tsx
-> Found three exports: Default, WithIcon, Disabled
-> Ask the user which one to capture, or whether to capture all of them
