creating-stories
Creates and modifies Storybook stories for Atomic components and sample pages. Uses MSW for API mocking, follows ui-kit conventions. Use when creating stories, adding component examples, building sample pages, or when user mentions Storybook, stories, or visual testing.
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
Creating Stories
Process
Step 1: Determine Story Type
Answer these questions:
- Is this a single component or a full page?
- Which interface type? (Search, Commerce, Insight, IPX, Recommendations)
- Is this a result template component?
- What API mocking is needed?
Locations:
- Components:
packages/atomic/src/components/<category>/<name>/<name>.new.stories.tsx - Pages:
packages/atomic/storybook-pages/<use-case>/<name>.new.stories.tsx
Step 2: Generate Template
This skill includes a small generator that renders Handlebars templates from .claude/skills/creating-stories/assets/.
# Component story
node .claude/skills/creating-stories/scripts/generate-story-template.mjs \
atomic-component-name --category search
# Result template component
node .claude/skills/creating-stories/scripts/generate-story-template.mjs \
atomic-result-field --category search --result
# Sample page
node .claude/skills/creating-stories/scripts/generate-story-template.mjs \
page-name --type page --category commerce
Allowed values:
-
--type:component(default),page -
--category:search(default),commerce,insight,ipx,recommendations
Notes:
-
--resultis only valid for--type component(using it with--type pageis an error).
Step 3: Complete the Story
- Add API mocking - Configure MSW harness for expected responses
- Create story variants - Add stories for different states (empty, error, selected)
- Add custom props - Set component-specific arguments
- Test interactions - Verify story renders and behaves correctly
For EndpointHarness overview and methods, see endpoint-harness-reference.md.
For advanced API mocking patterns, see msw-patterns.md.
For creating a new API mock domain, see creating-new-api-mock.md.
For component examples, see component-examples.md.
For page examples, see sample-page-examples.md.
Step 4: Validate
# Validate the story file
node .claude/skills/creating-stories/scripts/validate_story.mjs packages/atomic/src/components/.../component.new.stories.tsx
# Run Storybook to verify visually
cd packages/atomic && pnpm storybook
Story Structure
Component Story Anatomy
// 1. Create API harness at top level
const searchApiHarness = new MockSearchApi();
// 2. Get interface wrapper
const {decorator, play} = wrapInSearchInterface();
// 3. Get component helpers
const {events, args, argTypes, template} = getStorybookHelpers('atomic-name');
// 4. Configure meta
const meta: Meta = {
component: 'atomic-name',
decorators: [decorator],
parameters: {
msw: {handlers: [...searchApiHarness.handlers]},
},
beforeEach: () => {
searchApiHarness.searchEndpoint.clear();
},
play,
};
// 5. Export stories
export const Default: Story = {};
API Mocking Patterns
Default response:
// Uses base response automatically
Modify for all stories:
searchApiHarness.searchEndpoint.mock((response) => ({
...response,
results: response.results.slice(0, 10),
}));
Story-specific response:
export const NoResults: Story = {
beforeEach: () => {
searchApiHarness.searchEndpoint.mockOnce((response) => ({
...response,
results: [],
totalCount: 0,
}));
},
};
Available API Mocks
| Mock | Import | Use Case |
|---|---|---|
MockSearchApi |
@/storybook-utils/api/search/mock |
Search interface |
MockCommerceApi |
@/storybook-utils/api/commerce/mock |
Commerce interface |
MockInsightApi |
@/storybook-utils/api/insight/mock |
Insight interface |
MockAnswerApi |
@/storybook-utils/api/answer/mock |
Answer/RGA |
MockRecommendationApi |
@/storybook-utils/api/recommendation/mock |
Recommendations |
MockMachineLearningApi |
@/storybook-utils/api/machinelearning/mock |
ML/User Actions |
Interface Wrappers
| Wrapper | Import | Options |
|---|---|---|
wrapInSearchInterface |
@/storybook-utils/search/search-interface-wrapper |
skipFirstSearch, includeCodeRoot |
wrapInCommerceInterface |
@/storybook-utils/commerce/commerce-interface-wrapper |
skipFirstSearch, includeCodeRoot |
wrapInInsightInterface |
@/storybook-utils/insight/insight-interface-wrapper |
skipFirstSearch |
wrapInResultTemplate |
@/storybook-utils/search/result-template-wrapper |
autoLoad |
Reference Documentation
| Reference | When to Load |
|---|---|
| endpoint-harness-reference.md | EndpointHarness overview, methods, type safety |
| msw-patterns.md | Advanced MSW techniques, pagination, errors |
| creating-new-api-mock.md | Add a new mock domain when needed |
| component-examples.md | Facets, search box, pager, result components |
| sample-page-examples.md | Full page patterns for all interfaces |
Scripts
| Script | Purpose |
|---|---|
generate-story-template.mjs |
Generate story boilerplate from templates |
validate_story.mjs |
Validate created story files for correctness |
Templates
Templates in assets/ directory:
-
component.new.stories.tsx.hbs- Standard component story -
result-component.new.stories.tsx.hbs- Result template component -
page.new.stories.tsx.hbs- Sample page story
Validation Checklist
Before completing:
- Story file named
<component-name>.new.stories.tsx - MSW handlers included in parameters
-
beforeEachclears mocked responses - At least
Defaultstory exported - Component imports use path aliases (
@/storybook-utils/...) - For pages: initialization function and
playhandler included - Story follows patterns from similar components
Common Pitfalls
-
Forgetting to clear - Always
harness.endpoint.clear()inbeforeEach -
Not spreading base response - Always
{...response, field: value} -
Wrong import paths - Use
@/storybook-utils/...not relative paths -
Missing handlers - Include all harness handlers in
msw.handlers - Wrong decorator order - Result templates need specific order
Common Edge Cases
MSW Responses Not Being Consumed
Symptom: API calls return default responses instead of mocked ones.
Check:
- Endpoint path in harness matches actual API call
- HTTP method (GET/POST) is correct
- Handlers are included in MSW parameters:
msw: { handlers: [...harness.handlers] }
Responses Returned in Wrong Order
Symptom: Wrong response is returned for a queued sequence.
Solution: Ensure you're clearing in beforeEach, not afterEach:
beforeEach: () => {
harness.searchEndpoint.clear();
// Then enqueue in correct order
}
TypeScript Errors on Response Modification
Symptom: Type errors when modifying response objects.
Solution: Spread base response to maintain all required fields:
mockOnce((response) => ({
...response,
results: [], // Modify only what you need
}))
Multiple Stories Interfere With Each Other
Symptom: Stories fail when run together but pass individually.
Solution: Always clear queued responses in beforeEach:
const meta: Meta = {
beforeEach: () => {
searchApiHarness.searchEndpoint.clear();
// Then queue responses specific to each story
},
};
Examples
Read the usage examples in the source repository.
View source ↗Source history
- Indexed on
- 2026-01-20
- Index updated
- 2026-02-04
- 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!