Claude-skill-registry dev-storybook
Comprehensive Storybook skill for Vue 3 - story creation, auditing, component discovery, visual testing, and CI integration. Merged from dev-storybook, storybook-audit, and storybook-master.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/dev-storybook" ~/.claude/skills/majiayu000-claude-skill-registry-dev-storybook-8c05fd && rm -rf "$T"
skills/data/dev-storybook/SKILL.mddev-storybook
BUILD, AUDIT, and AUTOMATE Storybook stories for Vue 3 components with TypeScript. This comprehensive skill covers story creation, auditing existing stories for issues, component discovery and inventory, and CI/CD integration. Use when creating component documentation, fixing story compilation errors, auditing for display issues, or setting up automated testing workflows.
Core Responsibilities
- Story Creation: Write well-structured Storybook stories for Vue 3 components
- Error Resolution: Fix TypeScript and Vue compilation errors in stories
- Styling Patterns: Apply CSS correctly in Storybook without runtime template errors
- Component Props: Ensure correct prop types and event handlers
- Story Auditing: Detect and fix cutoff modals, store dependencies, design token violations
- Component Discovery: Scan codebase for components and generate inventory reports
- Automated Testing: Visual regression testing and accessibility compliance
- Story Streamlining: Ensure stories match the actual app appearance exactly
Story Streamlining (CRITICAL)
Trigger Keywords: "streamline", "streamlined", "match app", "looks different", "visual fidelity"
When user asks to "streamline" a Storybook story, they mean: Make the story look EXACTLY like the component appears in the actual app.
What "Streamlined" Means in This Project
CRITICAL: In FlowState, "streamlined" specifically means using glass morphism instead of solid black backgrounds.
- ❌ NOT streamlined: Solid black/opaque backgrounds (
,--glass-bg-solid
)rgba(0,0,0,0.95) - ✅ Streamlined: Semi-transparent backgrounds with blur so the purple gradient shows through
/* Streamlined = Glass Morphism */ background: rgba(30, 32, 45, 0.75); backdrop-filter: blur(24px) saturate(180%);
The app's signature look is glass panels floating over a purple/indigo gradient. If a component looks like a flat black box, it's NOT streamlined.
Streamlining Checklist
When streamlining a story, verify ALL of the following:
| Check | Requirement | How to Fix |
|---|---|---|
| 1. Use Actual Components | Story imports and renders the REAL Vue component, not a mockup | Import from |
| 2. App Background | Story background matches app's purple/indigo gradient | Use |
| 3. Glass Morphism | Modals/overlays use semi-transparent bg with blur, NOT solid black | Use + |
| 4. Design Tokens | All styling uses CSS variables, no hardcoded values | Replace and with |
| 5. Correct Props | Story passes the same props the component expects | Check in component |
| 6. Event Handlers | All emitted events have handlers | Add |
| 7. Mock Data | Data looks realistic, matches production patterns | Use actual Task/Project types |
Streamlining Workflow
1. IDENTIFY the component being streamlined └── Find the actual .vue component file └── Read its props, emits, and slots 2. COMPARE story vs app └── What does the story currently show? └── What does the actual app show? └── List the differences 3. FIX each difference: a. Background: Use var(--app-background-gradient) b. Components: Import actual components, not mockups c. Tokens: Replace hardcoded colors with CSS variables d. Props: Match component's defineProps interface e. Data: Use realistic mock data 4. VERIFY with user └── Ask user to check Storybook matches app
Background Color Reference
CRITICAL: The app uses a purple/indigo gradient, NOT neutral gray.
// ❌ WRONG - neutral gray (doesn't match app) background: var(--surface-primary); background: hsl(0, 0%, 12%); // ✅ CORRECT - app's purple/indigo gradient background: var(--app-background-gradient);
The
--app-background-gradient is defined in design-tokens.css:
--app-background-gradient: linear-gradient(135deg, hsl(220, 13%, 9%) 0%, hsl(240, 21%, 15%) 25%, hsl(250, 24%, 12%) 50%, hsl(260, 20%, 14%) 75%, hsl(220, 13%, 11%) 100%);
Example: Before/After Streamlining
Before (mockup, wrong background):
export const Default: Story = { render: () => ({ template: ` <div style="background: #1a1a1a; padding: 20px;"> <!-- Hardcoded mockup HTML --> <div class="fake-card"> <h2>Task Title</h2> <button>Action</button> </div> </div> ` }) }
After (streamlined, matches app):
import QuickSortCard from '@/components/QuickSortCard.vue' import { useTaskStore } from '@/stores/tasks' export const Default: Story = { render: () => ({ components: { QuickSortCard }, setup() { const mockTask = { id: '1', title: 'Real Task', priority: 'high', ... } return { mockTask } }, template: ` <div style=" min-height: 100vh; background: var(--app-background-gradient); padding: var(--space-8); "> <QuickSortCard :task="mockTask" @update-task="..." /> </div> ` }) }
Glass Morphism vs Solid Black (CRITICAL)
Problem: Components using
--glass-bg-solid or opaque black backgrounds look wrong because they block the app's purple gradient from showing through.
Solution: Use semi-transparent backgrounds with blur so the gradient is visible through the glass effect.
/* ❌ WRONG - Solid black, no glass effect */ background: var(--glass-bg-solid); /* rgba(0, 0, 0, 0.95) */ background: rgba(0, 0, 0, 0.95); background: #121214; /* ✅ CORRECT - Semi-transparent with blur (glass morphism) */ background: rgba(30, 32, 45, 0.75); backdrop-filter: blur(24px) saturate(180%); -webkit-backdrop-filter: blur(24px) saturate(180%); border: 1px solid var(--glass-border-medium);
Glass Morphism Recipe:
| Property | Value | Purpose |
|---|---|---|
| | Semi-transparent dark with slight purple tint |
| | Blur + color boost for depth |
| | Subtle edge definition |
| | Top highlight for polish |
When to use glass morphism:
- Modals and overlays
- Command palettes
- Dropdown menus
- Floating panels
- Any component that appears over the app background
Common Streamlining Issues
| Issue | Symptom | Fix |
|---|---|---|
| Mockup instead of component | Story shows different UI than app | Import actual component |
| Wrong background color | Black/gray instead of purple gradient | Use |
| Solid black modal | Modal looks flat, no depth | Use glass morphism with + |
| Hardcoded colors | Colors don't match design system | Use CSS variables |
| Missing components | Card missing buttons/badges | Import child components |
| Wrong spacing | Elements too cramped/spread | Use tokens |
Critical Rules
Vue 3 Template Restrictions
NEVER use
or <style>
tags inside runtime templates:<script>
// ❌ WRONG - Causes Vue compilation error template: ` <div> <style> .my-class { color: red; } </style> <MyComponent /> </div> ` // ✅ CORRECT - Apply styles globally or use inline styles template: ` <div> <MyComponent /> </div> `
Component Prop Verification
ALWAYS verify component props before writing stories:
# Check component interface grep -A 5 "interface Props" src/components/MyComponent.vue grep -A 5 "defineProps" src/components/MyComponent.vue
Example fix:
// Component expects: { isOpen: boolean, taskIds: string[] } // ❌ WRONG story args args: { isVisible: true, // Wrong prop name selectedTasks: [] // Wrong prop name } // ✅ CORRECT story args args: { isOpen: true, taskIds: ['1', '2', '3'] }
Import Requirements
ALWAYS include required Vue imports:
import type { Meta, StoryObj } from '@storybook/vue3' import { ref, reactive, computed } from 'vue' // Include all Vue APIs you use import MyComponent from '@/components/MyComponent.vue'
Common missing imports:
- For reactive stateref
- For reactive objectsreactive
- For computed propertiescomputed
- For watcherswatch
,onMounted
- For lifecycle hooksonUnmounted
Story Structure Pattern
Basic Story Template
import type { Meta, StoryObj } from '@storybook/vue3' import { ref } from 'vue' import MyComponent from '@/components/MyComponent.vue' const meta = { component: MyComponent, title: '📁 Category/MyComponent', tags: ['autodocs'], parameters: { layout: 'centered', // or 'fullscreen' docs: { description: { component: 'Component description here' } } } } satisfies Meta<typeof MyComponent> export default meta type Story = StoryObj<typeof meta> export const Default: Story = { args: { // Component props here isOpen: true, title: 'Example' }, render: (args) => ({ components: { MyComponent }, setup() { const isOpen = ref(args.isOpen) const handleClose = () => { isOpen.value = false } return { isOpen, handleClose, args } }, template: ` <MyComponent v-bind="args" :is-open="isOpen" @close="handleClose" /> ` }) }
Modal/Overlay Story Pattern
export const ModalExample: Story = { parameters: { layout: 'fullscreen' // Modal needs full screen }, args: { isOpen: true, title: 'Modal Title' }, render: (args) => ({ components: { MyModal }, setup() { const isOpen = ref(args.isOpen) return { isOpen, args, handleClose: () => { isOpen.value = false }, handleConfirm: () => { console.log('Confirmed') } } }, template: ` <div style="width: 100vw; height: 100vh; background: var(--surface-secondary);"> <MyModal v-bind="args" :is-open="isOpen" @close="handleClose" @confirm="handleConfirm" /> </div> ` }) }
Story Organization Standards
CRITICAL: Consolidate, Don't Duplicate
Problem: Too many similar stories create confusion and make components harder to understand.
Solution: Use focused, well-documented stories with clear purpose.
Recommended Story Structure (5-Story Pattern)
Every component story file should follow this organization:
1. Default Story (Primary with interactive controls)
export const Default: Story = { args: { variant: 'default', hoverable: false, // ... all props with defaults }, render: (args) => ({ components: { MyComponent }, setup() { return { args } }, template: ` <MyComponent v-bind="args" style="width: 320px;"> <div style="padding: var(--space-2);"> <h3 style="margin: 0 0 var(--space-2) 0; font-size: 16px; font-weight: 600;"> Default Component </h3> <p style="margin: 0; font-size: 14px; color: var(--text-secondary);"> Usage guidance explaining when/where to use this component. </p> </div> </MyComponent> ` }) }
Purpose: Interactive playground for testing all prop combinations via Controls panel.
2. Variants Story (Consolidated comparison)
export const Variants: Story = { parameters: { docs: { description: { story: `**Visual variants for different contexts:** - **Variant A**: When to use this variant - **Variant B**: When to use this variant - **Variant C**: When to use this variant` } } }, render: () => ({ components: { MyComponent }, template: ` <div style="display: flex; gap: var(--space-6); flex-wrap: wrap;"> <MyComponent variant="a" style="width: 280px;"> <div style="padding: var(--space-4);"> <h4>Variant A</h4> <p>Use when [specific context]</p> </div> </MyComponent> <MyComponent variant="b" style="width: 280px;"> <div style="padding: var(--space-4);"> <h4>Variant B</h4> <p>Use when [specific context]</p> </div> </MyComponent> </div> ` }) }
Purpose: Show all visual variants side by side with usage guidance.
Anti-pattern: Don't create separate stories for each variant (VariantA, VariantB, VariantC). Consolidate!
3. Effects/States Story (Realistic contexts)
export const Effects: Story = { parameters: { layout: 'fullscreen', docs: { description: { story: `**Effects for interaction and visual hierarchy:** - **Hoverable**: Use when components are clickable - **Glass**: Use on colorful/gradient backgrounds - **Elevated**: Use to emphasize important content` } } }, render: () => ({ components: { MyComponent }, template: ` <div style="padding: var(--space-8); display: flex; flex-direction: column; gap: var(--space-8);"> <!-- Hoverable --> <div> <h3>Hoverable Component</h3> <p>Use when components are clickable. Hover to see the effect.</p> <MyComponent hoverable style="width: 320px; cursor: pointer;"> Content here </MyComponent> </div> <!-- Glass Effect (SHOW IN REALISTIC CONTEXT) --> <div> <h3>Glass Effect</h3> <p>Use on colorful or gradient backgrounds.</p> <div style="padding: var(--space-8); background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: var(--radius-xl);"> <MyComponent glass style="width: 320px;"> Glass effect shown on actual gradient! </MyComponent> </div> </div> </div> ` }) }
Purpose: Show effects/states in realistic visual contexts (e.g., glass on gradient, not plain background).
Critical: Always show effects where they actually make sense visually.
4. WithSlots/Structure Story (Slot patterns)
export const WithSlots: Story = { parameters: { docs: { description: { story: `**Component supports slots for structured content:** - **Header**: For titles, actions, or badges - **Footer**: For metadata, timestamps, or action buttons - Use slots to create consistent, structured layouts` } } }, render: () => ({ components: { MyComponent }, template: ` <div style="display: flex; gap: var(--space-6); flex-wrap: wrap;"> <!-- Header only --> <MyComponent style="width: 300px;"> <template #header> <h3>Header Content</h3> </template> Main content </MyComponent> <!-- Footer only --> <MyComponent style="width: 300px;"> Main content <template #footer> Footer actions </template> </MyComponent> <!-- Both --> <MyComponent style="width: 300px;"> <template #header>Header</template> Main content <template #footer>Footer</template> </MyComponent> </div> ` }) }
Purpose: Show slot usage patterns side by side.
5. Real-World Example (Production-ready)
export const TaskCardExample: Story = { parameters: { docs: { description: { story: 'A realistic example showing how to combine variants, effects, and slots for production use.' } } }, render: () => ({ components: { MyComponent }, template: ` <MyComponent hoverable elevated style="width: 380px;"> <template #header> <!-- Complex header with badges, title, etc. --> </template> <div style="display: flex; flex-direction: column; gap: var(--space-4);"> <!-- Rich content with metadata, progress, etc. --> </div> <template #footer> <!-- Actions and metadata --> </template> </MyComponent> ` }) }
Purpose: Show production-ready example combining multiple features.
Usage Guidance Requirements
EVERY story must include usage guidance. Never show a variant without explaining when to use it.
Component-Level Documentation
const meta = { component: MyComponent, title: '🧩 Components/🔘 Base/MyComponent', tags: ['autodocs'], parameters: { layout: 'centered', docs: { description: { component: `Component description explaining its purpose. **When to use:** - Specific use case 1 - Specific use case 2 - Specific use case 3` } } }, argTypes: { variant: { control: 'select', options: ['default', 'outlined', 'filled'], description: 'Visual style variant', table: { type: { summary: 'string' }, defaultValue: { summary: 'default' } } } } }
Story-Level Documentation
export const Variants: Story = { parameters: { docs: { description: { story: `**Visual variants for different contexts:** - **Default**: Standard style (use for X) - **Outlined**: Transparent background (use for Y) - **Filled**: Solid background (use for Z)` } } } }
Visual Context Best Practices
✅ GOOD: Show effects in realistic contexts
// Glass effect on gradient <div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: var(--space-8);"> <MyComponent glass> Now the glass effect actually makes sense! </MyComponent> </div> // Elevated card on page <div style="padding: var(--space-8); background: var(--surface-primary);"> <MyComponent elevated> Extra shadow creates depth on the page </MyComponent> </div>
❌ BAD: Show effects on plain backgrounds
// Glass effect on plain background (can't see blur!) <MyComponent glass> Glass effect is invisible here </MyComponent> // Elevated without context (shadow purpose unclear) <MyComponent elevated> Why is this elevated? </MyComponent>
ArgTypes Standards
Always include comprehensive argTypes with descriptions:
argTypes: { variant: { control: 'select', options: ['default', 'outlined', 'filled'], description: 'Visual style variant', table: { type: { summary: 'string' }, defaultValue: { summary: 'default' } } }, hoverable: { control: 'boolean', description: 'Add hover effects (elevation & transform)', table: { type: { summary: 'boolean' }, defaultValue: { summary: 'false' } } } }
Story Consolidation Checklist
Before creating multiple similar stories, ask:
- Can these variants be shown side by side in one story?
- Does each story explain WHEN to use it?
- Are effects shown in realistic visual contexts?
- Is the Default story using args for interactivity?
- Does the documentation include "When to use" guidance?
Target: 5-7 focused stories per component, NOT 12+ redundant stories.
CSS Styling Patterns
Option 1: Inline Styles (Preferred for simple cases)
template: ` <div style="padding: 20px; background: var(--surface-primary);"> <MyComponent /> </div> `
Option 2: CSS Variables (Use design tokens)
template: ` <div style=" padding: var(--space-4); background: var(--surface-primary); border-radius: var(--radius-lg); "> <MyComponent /> </div> `
Option 3: Global Styling (For component-wide changes)
Modify the component's scoped styles directly in the
.vue file instead of trying to override in stories.
Common Errors and Fixes
Error: "Tags with side effect (<script> and <style>) are ignored"
Cause: Attempting to use
<style> or <script> tags in runtime template
Fix: Remove the tags and use inline styles or global component styles
// Before (causes error) template: `<div><style>.foo{}</style><Component /></div>` // After (works) template: `<div style="..."><Component /></div>`
Error: "Cannot find module '@/components/...'"
Cause: TypeScript path resolution in story files
Fix: This is usually a TypeScript check error only. Storybook will still work because Vite handles the paths. You can ignore or configure
tsconfig.json to include story files.
Error: "Cannot find name 'ref'"
Cause: Missing Vue import
Fix: Add
import { ref } from 'vue'
Error: "Missing required prop: 'propName'"
Cause: Component expects different props than story provides
Fix:
- Check component props:
grep -A 5 "defineProps" src/components/MyComponent.vue - Update story args to match
- Ensure event handlers match emitted events
Storybook Configuration
Running Storybook
npm run storybook # Start on port 6006 npm run build-storybook # Build static site
Story File Patterns
Stories are auto-discovered from:
src/**/*.stories.tssrc/**/*.stories.tsx
Decorators Pattern
decorators: [ () => ({ template: '<div style="width: 100%; height: 100vh;"><story /></div>' }) ]
Mock Data Patterns
Creating Mock Store
const createMockStore = (overrides = {}) => ({ state: { items: [], ...overrides }, getItem: (id: string) => mockData.find(item => item.id === id), updateItem: (id: string, data: any) => { console.log('Updated:', id, data) } }) export const WithMockStore: Story = { render: () => ({ setup() { const store = createMockStore({ items: mockItems }) return { store } } }) }
Design System Colors Fix
CRITICAL: Ensure design tokens use neutral grays (no blue tint)
Blue-tinted grays (WRONG):
--gray-950: 218, 33%, 12%; /* Hue 218 = Blue! */ --gray-900: 217, 33%, 17%; /* High saturation = Color tint! */
Neutral grays (CORRECT):
--gray-950: 0, 0%, 12%; /* Hue 0, Saturation 0% = Neutral */ --gray-900: 0, 0%, 17%; /* No color tint */
Check for blue tint:
grep "gray-9" src/assets/design-tokens.css
Testing Stories
- Visual Check: Open http://localhost:6006 and verify rendering
- Interaction: Test interactive elements (buttons, inputs, modals)
- Responsive: Check different viewport sizes
- Error Console: Look for Vue warnings or errors
Best Practices
- One Component Per Story File: Each component gets its own
.stories.ts - Multiple Variants: Create stories for different states (Default, Loading, Error, etc.)
- Descriptive Names: Use clear story names like
,Default
,WithDataErrorState - Documentation: Add descriptions using
parameters.docs.description - Args Controls: Use
to make props interactiveargTypes - Real Data: Use realistic mock data that represents actual use cases
Common Story Variants
export const Default: Story = { /* Basic usage */ } export const Loading: Story = { /* Loading state */ } export const Error: Story = { /* Error state */ } export const WithData: Story = { /* Populated with data */ } export const Empty: Story = { /* Empty state */ } export const Interactive: Story = { /* Full interaction demo */ }
Resources
- Storybook Docs: https://storybook.js.org/docs/vue/get-started/introduction
- Vue 3 + Storybook: https://storybook.js.org/docs/vue/writing-stories/introduction
- Component Story Format (CSF): https://storybook.js.org/docs/api/csf
PART 2: Story Auditing (Merged from storybook-audit)
This section provides systematic auditing capabilities for detecting and fixing common Storybook issues.
Trigger Keywords
Activate auditing capabilities when user mentions:
- "audit storybook", "fix storybook stories", "storybook cut off"
- "storybook store error", "storybook database error"
- "storybook modal cutoff", "storybook rendering issues"
- "Cannot find name 'ref'", "missing imports", "Vue import error"
- "missing event handlers", "modal won't close", "buttons don't work"
User Clarification Protocol
CRITICAL: Before attempting fixes, ask clarifying questions to understand the exact issue.
Questions to Ask
When user reports a Storybook issue, ask:
-
Issue Type Clarification:
- "Is this happening on the Docs page or the Canvas/Story page?"
- "Is the component being cut off, showing an error, or not rendering at all?"
-
Component Context:
- "What type of component is this? (Modal, Context Menu, Dropdown, Form, etc.)"
- "Does this component use any Pinia stores?"
- "Does the component have dynamic height (expandable sections, submenus)?"
-
Error Details:
- "Are there any errors in the browser console?"
- "Can you share the exact error message?"
Decision Tree
User reports Storybook issue ├── "cut off" / "clipped" / "can't see" │ └── Ask: "Docs page or Canvas?" + "Component type?" │ └── Likely: iframe height issue → Check 1 │ ├── "error" / "won't render" / "database" │ └── Ask: "Console error message?" │ └── Likely: Store dependency → Check 2 │ ├── "doesn't match" / "wrong props" │ └── Ask: "Which props are incorrect?" │ └── Likely: Props mismatch → Check 4 │ ├── "Cannot find name 'ref'" / "Cannot find name 'computed'" │ └── Ask: "Which Vue APIs are you using in setup()?" │ └── Likely: Missing imports → Check 7 │ ├── "buttons don't work" / "can't close modal" │ └── Ask: "What happens when you click [button]?" │ └── Likely: Missing event handlers → Check 8 │ └── Unknown └── Run full audit, then ask about findings
Audit Checks
Check 1: Iframe Height
Issue: Docs pages cut off modals, popups, or dropdowns
Detection:
# Find stories with potentially low iframe heights grep -rn "iframeHeight" src/stories/ | grep -E "iframeHeight: [0-5][0-9]{2}," # Find stories without explicit height grep -L "iframeHeight" src/stories/**/*.stories.ts
Component Type Guidelines:
| Component Type | Minimum Height | Notes |
|---|---|---|
| Simple components | 400px | Buttons, inputs, badges |
| Context menus | 600px | May have submenus |
| Dropdowns | 500px | Check max items |
| Modals (small) | 700px | Confirmation dialogs |
| Modals (large) | 900px | Forms, settings |
| Full-page overlays | 100vh | Use fullscreen layout |
| Components with submenus | 900px+ | Cascading menus need more |
Fix Pattern A: Iframe Height (Standard):
parameters: { layout: 'fullscreen', docs: { story: { inline: false, iframeHeight: 900, // Adjust based on component type } } },
Fix Pattern B: Inline Relative Container (Robust for Storybook 8/10):
parameters: { layout: 'fullscreen', docs: { story: { inline: true } } }, decorators: [ () => ({ template: ` <div class="story-container" style=" background: var(--glass-bg-solid); height: 850px; width: 100%; position: relative; overflow: hidden; display: flex; align-items: center; justify-content: center; border-radius: 8px; "> <story /> </div> ` }) ]
Check 2: Store Dependencies (Pinia)
Issue: Stories import real Pinia stores which initialize PouchDB → causes database errors
Detection:
# Find stories importing stores grep -rn "from '@/stores" src/stories/ grep -rn "useTaskStore\|useTimerStore\|useCanvasStore\|useUIStore" src/stories/
Fix Options (in order of preference):
Option A - Props Only (best for presentational components):
// Pass data via props, no store needed const mockTask: Task = { id: '1', title: 'Test Task', status: 'planned', priority: 'high', } export const Default: Story = { args: { task: mockTask, onEdit: () => console.log('edit'), onDelete: () => console.log('delete'), } }
Option B - Fresh Pinia Decorator (for components requiring store):
// Create decorator: src/stories/decorators/freshPiniaDecorator.ts import { createPinia, setActivePinia } from 'pinia' export const freshPiniaDecorator = (story: any) => { setActivePinia(createPinia()) return story() }
Check 3: Template Validation
Issue: Runtime templates contain
<style> or <script> tags causing Vue errors
Detection:
grep -rn "template:.*<style>" src/stories/ grep -rn "template:.*<script>" src/stories/
Check 4: Props Mismatch
Issue: Story args don't match component prop definitions
Detection:
# Get component props grep -A 30 "defineProps" src/components/[ComponentName].vue # Get story args grep -A 15 "args:" src/stories/[ComponentName].stories.ts
Common Mismatches:
| Story Arg | Actual Prop | Fix |
|---|---|---|
| | Use |
| | Use |
| emit | Add handler |
Check 5: Layout Parameter
Issue: Modals/overlays using
layout: 'centered' causing cutoff
Detection:
grep -l "Modal\|Overlay\|Dialog\|Popup\|Drawer" src/stories/**/*.ts | \ xargs grep -L "layout: 'fullscreen'"
Check 6: Design Token Enforcement
Issue: Stories or decorators use hardcoded colors instead of CSS design tokens
Detection:
# Find hardcoded hex colors in stories grep -rn "#[0-9a-fA-F]\{3,8\}" src/stories/ --include="*.ts" --include="*.vue" # Find hardcoded rgba values grep -rn "rgba\s*(" src/stories/ --include="*.ts" --include="*.vue"
Token Categories to Use:
| Purpose | CSS Variable |
|---|---|
| Priority High | |
| Priority Medium | |
| Priority Low | |
| Glass background | , |
| Glass border | |
| Modal/Dropdown bg | , |
| Text primary | |
| Surface colors | , |
Check 7: Missing Vue Imports
Issue: Stories use Vue APIs without importing them
Fix Pattern:
// Add all used Vue APIs import { ref, computed, watch, onMounted } from 'vue'
Check 8: Event Handlers
Issue: Stories don't provide handlers for critical events
Critical Events Checklist:
For Modal/Overlay components:
-
- User closes modal@close -
- User confirms action@confirm -
- User cancels action@cancel
For Form components:
-
- User submits form@submit -
- User cancels form@cancel
Full Audit Workflow
Run this bash script for a complete audit:
echo "=== STORYBOOK AUDIT REPORT ===" echo "" echo "=== 1. Store Dependencies ===" grep -rn "from '@/stores" src/stories/ 2>/dev/null | head -20 || echo "None found" echo "" echo "=== 2. Low Iframe Heights (<600px) ===" grep -rn "iframeHeight: [0-5][0-9]{2}," src/stories/ 2>/dev/null || echo "None found" echo "" echo "=== 3. Template Style/Script Tags ===" grep -rn "template:" src/stories/ 2>/dev/null | grep -E "<style|<script" || echo "None found" echo "" echo "=== 4. Modals Without Fullscreen ===" for f in $(find src/stories -name "*.stories.ts" 2>/dev/null); do if grep -q "Modal\|Overlay\|Dialog" "$f" && ! grep -q "fullscreen" "$f"; then echo "$f: NEEDS FULLSCREEN" fi done echo "" echo "=== 5. Hardcoded Colors (Token Violations) ===" grep -rn "#[0-9a-fA-F]\{3,8\}" src/stories/ --include="*.ts" 2>/dev/null | head -15 || echo "None found" echo "" echo "=== Audit Complete ==="
Component-Specific Guidelines
TaskContextMenu
- Minimum height: 900px (has cascading submenus)
- Needs mock task data, not store
- All event handlers should be noops or console.log
- Layout: fullscreen required
ContextMenu
- Minimum height: 600px
- Position must be calculated in render function
- Use
for centeringonMounted
Modal Components (General)
- Always use
layout: 'fullscreen' - Wrap in full-height container div
- Provide toggle mechanism for interactive demos
- Test both open and closed states
Auth Components
- Background:
var(--glass-bg-solid) - Border: None (clean glass look)
- Layout:
with fixed height (600px-800px)inline: true
PART 3: Component Discovery & Automation (Merged from storybook-master)
This section provides automated component discovery, story generation, and CI integration.
4-Phase Workflow
Phase 1: Component Discovery & Inventory
Smart Source Scanning:
- Multi-framework detection (React, Vue, Svelte, Web Components)
- Pattern-based classification using folder structures
- Metadata extraction from prop types and interfaces
Usage:
python3 scripts/phase1_discovery.py
Output Files:
: Complete component inventorystorybook-inventory.csv
: Undocumented components reportmissing-stories-report.md
: Component-to-story mappingcomponent-update-map.json
Phase 2: Autodocs & Story Automation
Story Generation:
- CSF3 story format generation
- Prop-driven controls auto-generation
- Documentation blocks creation
Usage:
python3 scripts/phase2_generation.py --auto-fix
Phase 3: Automated Visual & Interaction Testing
Visual Test Harness:
- Snapshot testing for visual regression
- Cross-browser testing
- Accessibility compliance (axe-core, WCAG 2.1 AA)
Phase 4: CI/CD Integration
CI Enforcement:
- Build validation and coverage enforcement
- Quality gates for merging
- Automated PR comments
Configuration
Create
.storybook/skill-config.yml:
discovery: component_paths: - "src/components/**/*" story_paths: - "src/**/*.stories.*" ignore_patterns: - "*.test.*" - "node_modules/**" generation: autodocs: true controls: true accessibility_testing: true testing: visual_testing: enabled: true tool: "chromatic" accessibility: enabled: true standards: ["WCAG2.1AA"] ci: enforce_coverage: true fail_on_missing_stories: true
Scripts Available
Located in
scripts/ directory:
- Main orchestrator for all phasesrun_storybook_master.py
- Component discoveryphase1_discovery.py
- Story generationphase2_generation.py
Self-Learning Protocol
This skill learns from successful fixes. When a solution works:
-
Document the solution by asking user:
- "This fix worked. Should I add it to the skill's knowledge base?"
- "What was the root cause?"
-
Update the skill with user approval:
- Add new component-specific guidelines
- Add new error patterns and fixes
- Update height recommendations
Example Files
Before/after examples are available in
examples/ directory:
- Iframe height fix for modalsbefore-after-modal-iframe.md
- Height fix for cascading menusbefore-after-contextmenu-height.md
- Store dependency fixbefore-after-store-dependency.md
- Template style tag fixbefore-after-template-style.md
- Props matching component definitionsbefore-after-props-mismatch.md
- Missing Vue imports fixbefore-after-missing-imports.md
- Missing event handlers fixbefore-after-event-handlers.md
References
Best practices reference available in
references/storybook-best-practices.md.
When to use this skill: Creating or fixing Storybook stories, resolving story compilation errors, documenting Vue 3 components, setting up component showcases, auditing stories for issues, automating component discovery.
MANDATORY USER VERIFICATION REQUIREMENT
Policy: No Fix Claims Without User Confirmation
CRITICAL: Before claiming ANY issue, bug, or problem is "fixed", "resolved", "working", or "complete", the following verification protocol is MANDATORY:
Step 1: Technical Verification
- Run all relevant tests (build, type-check, unit tests)
- Verify no console errors
- Take screenshots/evidence of the fix
Step 2: User Verification Request
REQUIRED: Use the
AskUserQuestion tool to explicitly ask the user to verify the fix:
"I've implemented [description of fix]. Before I mark this as complete, please verify: 1. [Specific thing to check #1] 2. [Specific thing to check #2] 3. Does this fix the issue you were experiencing? Please confirm the fix works as expected, or let me know what's still not working."
Step 3: Wait for User Confirmation
- DO NOT proceed with claims of success until user responds
- DO NOT mark tasks as "completed" without user confirmation
- DO NOT use phrases like "fixed", "resolved", "working" without user verification
Step 4: Handle User Feedback
- If user confirms: Document the fix and mark as complete
- If user reports issues: Continue debugging, repeat verification cycle
Prohibited Actions (Without User Verification)
- Claiming a bug is "fixed"
- Stating functionality is "working"
- Marking issues as "resolved"
- Declaring features as "complete"
- Any success claims about fixes
Required Evidence Before User Verification Request
- Technical tests passing
- Visual confirmation via Playwright/screenshots
- Specific test scenarios executed
- Clear description of what was changed
Remember: The user is the final authority on whether something is fixed. No exceptions.