Write or update Storybook stories for Vue components in ComfyUI_frontend. Use when adding, modifying, reviewing, or debugging `.stories.ts` files, Storybook docs, component demos, or visual catalog entries in `src/` or `apps/desktop-ui/`.
feat/* or fix/* branch. Base PRs on the local main, not a fork branch.rg --files src apps | rg '\.stories\.ts$'rg -n "title:\\s*'" src apps --glob '*.stories.ts'ComponentName.stories.ts.@storybook/vue3-vite. Some stories under apps/desktop-ui still use @storybook/vue3; keep the local convention for that area.tags: ['autodocs'] unless the surrounding stories in that area intentionally omit it.ComponentPropsAndSlots<typeof Component> when it helps with prop and slot typing.render functions stateful when needed. Use ref(), computed(), and toRefs(args) instead of mutating Storybook args directly.args.default or other slot-shaped args when the component content is provided through slots.ComponentExposed only when a component's exposed API breaks the normal Storybook typing.Do not invent titles from scratch when a close sibling story already exists. Match the nearest domain pattern.
| Component area | Typical title pattern |
|---|---|
src/components/ui/button/Button.vue | Components/Button/Button |
src/components/ui/input/Input.vue | Components/Input |
src/components/ui/search-input/SearchInput.vue | Components/Input/SearchInput |
src/components/common/SearchBox.vue | Components/Input/SearchBox |
src/renderer/extensions/vueNodes/widgets/components/* | Widgets/<WidgetName> |
src/platform/assets/components/* | Platform/Assets/<ComponentName> |
apps/desktop-ui/src/components/* | Desktop/Components/<ComponentName> |
apps/desktop-ui/src/views/* | Desktop/Views/<ViewName> |
If multiple patterns seem plausible, follow the closest sibling story in the same folder tree.
v-modelexport const Default: Story = {
render: (args) => ({
components: { MyComponent },
setup() {
const { disabled, size } = toRefs(args)
const value = ref('Hello world')
return { value, disabled, size }
},
template:
'<MyComponent v-model="value" :disabled="disabled" :size="size" />'
})
}
const meta: Meta<ComponentPropsAndSlots<typeof Button>> = {
argTypes: {
default: { control: 'text' }
},
args: {
default: 'Button'
}
}
export const SingleButton: Story = {
render: (args) => ({
components: { Button },
setup() {
return { args }
},
template: '<Button v-bind="args">{{ args.default }}</Button>'
})
}
export const AllVariants: Story = {
render: () => ({
components: { MyComponent },
template: `
<div class="grid gap-4 sm:grid-cols-2">
<MyComponent />
<MyComponent disabled />
<MyComponent loading />
<MyComponent invalid />
</div>
`
})
}
Disabled, Loading, Invalid, WithPlaceholder, AllSizes, or EdgeCases.AllVariants, AllSizes, or EdgeCases when side-by-side comparison is useful.SimplifiedWidget object. Build it in setup() and use computed() when args change widget.options.bg-base-background and fixed-width containers.backgrounds parameters and may intentionally keep the older Storybook import style used by neighboring files.bg-base-background and bg-node-component-surface instead of dark: variants or hardcoded theme assumptions.Default only when that matches nearby conventionstags: ['autodocs']pnpm storybookpnpm typecheckpnpm lintv-model components.dark: Tailwind variants in story wrappers.layout: 'centered' or a Default export; follow the nearest existing pattern.