一键导入
storybook-update-component
Update existing Storybook component stories to reflect component changes (props, slots, events)
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Update existing Storybook component stories to reflect component changes (props, slots, events)
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | storybook-update-component |
| description | Update existing Storybook component stories to reflect component changes (props, slots, events) |
This skill provides comprehensive guidance for updating existing component stories in the Console Storybook, ensuring documentation stays synchronized with component changes.
When components are modified (props added/removed, slots changed, events updated), their Storybook stories must be updated to reflect these changes. This skill ensures stories remain accurate, complete, and build successfully.
Storybook Configuration:
storybook/src/stories/templates/{ComponentName}.stories.jsvite.config.js (defines aliases)storybook/.storybook/main.js (resolves aliases)Path Aliases (configured in Storybook):
'@' → '../../src'
'@templates' → '../../src/templates'
'@components' → '../../src/components'
Import Patterns in Stories:
import Component from '@/templates/{component-name}/index.vue'import Component from '@/components/{component-name}/index.vue'Build Command:
yarn storybook:build
The user provides: storybook-update-component @filepath
@src/templates/my-component/index.vue)@storybook/src/stories/templates/MyComponent.stories.js)Read the provided file to determine:
If component file provided:
src/templates/ or src/components/If story file provided:
If package.json export name provided:
Component Location Resolution:
// From story import
import ActionBarBlock from '@/templates/action-bar-block/index.vue'
// Resolves to: src/templates/action-bar-block/index.vue
import SomeComponent from '@/components/some-component/index.vue'
// Resolves to: src/components/some-component/index.vue
Extract from component:
// Vue 3 Composition API
const props = defineProps({
prop1: { type: Boolean, default: false },
prop2: { type: String, default: '' },
prop3: { type: Number, default: 0 }
})
const emit = defineEmits(['update', 'submit'])
// Template
<template>
<div>
<slot name="header"></slot>
<slot>Default slot</slot>
<slot name="footer"></slot>
</div>
</template>
Parse and categorize:
defineProps or props option
<slot> tags in template
defineEmits or $emit calls
Locate story file:
# For templates
storybook/src/stories/templates/{ComponentName}.stories.js
# For components
storybook/src/stories/components/{ComponentName}.stories.js
If story file doesn't exist:
storybook-add-component skill insteadIf story file exists: Read and parse:
title - Component titleargTypes - Prop documentationparameters - Component descriptiontags - Autodocs tagCreate comparison matrix:
| Component Feature | Story Documentation | Status |
|---|---|---|
prop1: Boolean | ✅ in argTypes | MATCH |
prop2: String | ✅ in argTypes | MATCH |
prop3: Number | ❌ missing | MISSING |
slot default | ✅ in render | MATCH |
slot header | ❌ missing | MISSING |
slot footer | ✅ in render | MATCH |
event update | ❌ missing | MISSING |
Categorize changes:
For NEW props:
argTypes: {
// ... existing props
newProp: {
control: 'text', // or 'boolean', 'number', 'select', 'object'
description: 'Description of newProp (inferred from component or generic)'
}
}
For REMOVED props:
argTypes: {
// Remove the deleted prop from argTypes
// Also remove from any story args that use it
}
For MODIFIED props:
argTypes: {
// Update control type if type changed
// Update description if behavior changed
// Update default value in story args
propWithNewType: {
control: 'select', // Changed from 'text'
options: ['option1', 'option2'],
description: 'Updated description'
}
}
For NEW slots:
// Add new story variant demonstrating the slot
export const WithAllSlots = {
render: (args) => ({
components: { Component },
setup() {
return { args };
},
template: `
<Component v-bind="args">
<template #existingSlot>
<div>Existing slot</div>
</template>
<template #newSlot>
<div>New slot content</div>
</template>
</Component>
`
}),
args: { ... }
};
For REMOVED slots:
// Remove slot from render functions
// Remove entire story if it only demonstrated removed slot
For events:
// Events don't have argTypes in Storybook
// Document in parameters.docs.description.component or add to story template
parameters: {
docs: {
description: {
component: `
Component description.
**Events:**
- \`update\`: Emitted when value changes
- \`submit\`: Emitted when form submits
`
}
}
}
For components with dependency injection:
// Component uses inject('dialogRef')
// Story needs a wrapper component to provide the injection
import { ref, provide } from 'vue';
// Wrapper component mimics the provider
const ComponentWrapper = {
components: { Component },
props: {
// Props that will be passed to injected data
prop1: { type: String, default: 'value' }
},
setup(props) {
// Create the injection data
const injectedData = ref({
data: { prop1: props.prop1 },
close: () => console.log('close')
});
// Provide the injection
provide('dialogRef', injectedData);
return {};
},
template: `<Component />`
};
// Story uses wrapper
export const Default = {
render: () => ({
components: { ComponentWrapper },
template: '<ComponentWrapper prop1="value" />'
})
};
When you need a wrapper:
inject('dialogRef') or similarSee Troubleshooting section for more details.
If component purpose changed:
parameters: {
docs: {
description: {
component: 'Updated description reflecting component changes.'
}
}
}
Check existing story variants are still valid:
Update variant stories if needed:
export const Loading = {
args: {
loading: true,
// Add new required props
newProp: 'default value'
}
};
Run build command:
yarn storybook:build
Check for:
If build fails:
Open Storybook:
yarn storybook:dev
Check:
yarn storybook:build completes without errors// Component has prop
const props = defineProps({
newProp: String
})
// Story argTypes doesn't have it
argTypes: {
oldProp: { ... }
// newProp missing!
}
// Component doesn't have prop
const props = defineProps({
existingProp: String
})
// Story argTypes has it
argTypes: {
existingProp: { ... },
removedProp: { ... } // Should be removed!
}
// Component template has slot
<template>
<div>
<slot name="existing"></slot>
<slot name="newSlot"></slot> // New!
</div>
</template>
// Story doesn't show it
template: `
<Component>
<template #existing>...</template>
// #newSlot missing!
</Component>
`
// Component prop type changed
const props = defineProps({
status: {
type: String,
validator: (v) => ['active', 'inactive'].includes(v) // Now enum!
}
})
// Story has wrong control
argTypes: {
status: {
control: 'text' // Should be 'select' with options!
}
}
| Prop Type | Control Type | Additional Config |
|---|---|---|
Boolean | 'boolean' | None |
String | 'text' | None |
String (enum) | 'select' | options: [...] |
Number | 'number' | None |
Array | 'object' | None |
Object | 'object' | None |
Function | 'object' | None |
Date | 'date' | None |
// Component change
const props = defineProps({
disabled: { type: Boolean, default: false } // New prop
})
// Story update
argTypes: {
// ... existing
disabled: {
control: 'boolean',
description: 'Disables the component'
}
}
// Update all story variants
export const Default = {
args: {
// ... existing
disabled: false // Add default
}
};
export const Disabled = { // New variant
args: {
disabled: true
}
};
// Component change
<template>
<div>
<slot></slot>
// <slot name="deprecated"> removed!
</div>
</template>
// Story update
export const Default = {
render: (args) => ({
components: { Component },
setup() {
return { args };
},
template: `
<Component v-bind="args">
// Remove deprecated slot
</Component>
`
}),
args: { ... }
};
// Component change
const props = defineProps({
size: {
type: String,
validator: (v) => ['small', 'medium', 'large'].includes(v) // Changed from any string
}
})
// Story update
argTypes: {
size: {
control: 'select', // Changed from 'text'
options: ['small', 'medium', 'large'],
description: 'Component size'
}
}
// Add size variants
export const Small = {
args: { size: 'small' }
};
export const Medium = {
args: { size: 'medium' }
};
export const Large = {
args: { size: 'large' }
};
Before completing, verify:
yarn storybook:buildStory Not Found:
storybook/src/stories/templates/storybook/src/stories/components/Build Fails After Update:
Props Not Appearing:
Slots Not Rendering:
components: { Component } is included<template #slotName> syntaxWrong Import Path:
@/templates/ for template components@/components/ for other componentsComponent Requires Injection:
If component uses inject() and story fails or renders nothing:
inject('dialogRef') or similarprovide() in wrapper's setup to provide expected injectiondialogRef automatically in productionDebugging Injection Issues:
// Add console.log to understand what component expects
setup() {
const injected = inject('dialogRef');
console.log('Expected injection:', injected);
// This will show undefined if not provided
}
Component change detected:
// New prop added to component
const props = defineProps({
loading: { type: Boolean, default: false },
inDrawer: { type: Boolean, default: false },
cancelDisabled: { type: Boolean, default: false },
primaryActionLabel: { type: String, default: 'Save' },
secondaryActionLabel: { type: String, default: 'Cancel' },
goBack: { type: Function }, // Function prop
size: { type: String, validator: v => ['small', 'medium', 'large'].includes(v) } // New!
})
Story update:
// Read existing story
// Add to argTypes
argTypes: {
// ... existing props
size: { // New!
control: 'select',
options: ['small', 'medium', 'large'],
description: 'Size variant for the action bar'
}
}
// Update story args
export const Default = {
args: {
// ... existing
size: 'medium' // Add default
}
};
// Create new variants
export const Small = {
args: {
loading: false,
size: 'small'
}
};
export const Large = {
args: {
loading: false,
size: 'large'
}
};
Component change detected:
// Component template changed
<template>
<div>
<slot name="header"></slot>
<slot></slot>
// <slot name="deprecated"> removed
</div>
</template>
Story update:
// Find stories using deprecated slot
export const OldStory = {
render: (args) => ({
components: { Component },
setup() {
return { args };
},
template: `
<Component v-bind="args">
<template #header>Header</template>
<template #deprecated>Remove this</template> // Remove!
</Component>
`
}),
args: { ... }
};
// Updated version
export const OldStory = {
render: (args) => ({
components: { Component },
setup() {
return { args };
},
template: `
<Component v-bind="args">
<template #header>Header</template>
</Component>
`
}),
args: { ... }
};
.js) not TypeScript@ maps to /src directory