用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/mikailustuner/OmniRule --skill storybook-patterns命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
正在显示 SKILL.md
| name | storybook-patterns |
| description | Storybook: Component documentation, Stories writing, Addons, Controls, Testing stories. |
| triggers | {"files":[".storybook/main.ts",".storybook/preview.ts"],"directories":["stories/","src/**/*.stories.ts"],"keywords":["Storybook","storybookjs","component documentation","controls"]} |
| auto_load_when | Building component libraries or documenting UI components |
| agent | frontend-ops |
| tools | ["Read","Write","Bash"] |
Focus: Component documentation, story writing, addons
Basic Story (CSF 3.0):
import Button from './Button.svelte'
export default {
title: 'Components/Button',
component: Button,
argTypes: {
onClick: { action: 'clicked' }
}
}
export const Primary = {
args: {
variant: 'primary',
label: 'Primary Button'
}
}
export const Secondary = {
args: {
variant: 'secondary',
label: 'Secondary Button'
}
}
Multi-component Story:
export const ButtonGroup = {
render: (args) => ({
Component: ButtonGroup,
props: args
}),
args: {
buttons: [
{ label: 'One', variant: 'primary' },
{ label: 'Two', variant: 'secondary' }
]
}
}
ArgTypes:
export default {
component: Button,
argTypes: {
variant: {
control: 'select',
options: ['primary', 'secondary', 'danger']
},
size: {
control: 'radio',
options: ['sm', 'md', 'lg']
},
disabled: { control: 'boolean' },
label: { control: 'text' },
loading: { control: 'boolean' }
}
}
Regex Control:
description: {
control: 'text',
validate: (val) => val.length > 3 || 'Too short'
}
Object/Array Control:
items: {
control: 'object',
defaultValue: [{ id: 1, name: 'Item 1' }]
}
Color Picker:
color: {
control: 'color'
}
Global Decorator (.storybook/preview.ts):
import '../src/styles/global.css'
export const decorators = [
(story) => ({
Component: story,
props: {
...story.args,
// Add global props
}
})
]
Theme Decorator:
import { ThemeProvider } from 'my-design-system'
export const decorators = [
(story) => ({
Component: ThemeProvider,
props: {
theme: 'dark',
children: story()
}
})
]
Router Decorator:
export const decorators = [
(story) => ({
Component: MemoryRouter,
props: { initialEntries: ['/'] },
children: story()
})
]
Play Function (Interaction Testing):
export const Clickable = {
play: async ({ canvasElement }) => {
const button = canvasElement.querySelector('button')
await userEvent.click(button)
// Assertions
}
}
Component Tests:
import { render, screen, fireEvent } from '@testing-library/svelte'
import Button from './Button.svelte'
test('renders button', () => {
render(Button, { props: { label: 'Test' } })
expect(screen.getByText('Test')).toBeInTheDocument()
})
test('clicks button', async () => {
const handleClick = vi.fn()
render(Button, { props: { onClick: handleClick } })
await fireEvent.click(screen.getByRole('button'))
expect(handleClick).toHaveBeenCalled()
})
❌ No stories for components
✅ Every component needs at least one story
❌ Stories without controls
✅ Make props editable for easier testing
❌ Not testing interactions
✅ Use play function for click/hover tests
❌ Hardcoded values in stories
✅ Use args for flexibility
❌ No documentation
✅ Add description to components and args
❌ Not using controls
✅ Enable controls for all props
| Feature | Syntax | Note |
|---|---|---|
| Story | export const Name = { args: {} } | Define story |
| Controls | argTypes with control | Editable props |
| Decorator | decorators: [(story) => {...}] | Wrap stories |
| Play | play: async ({ canvasElement }) => | Interaction test |
| Actions | onClick: { action: 'clicked' } | Event handler |
基于 SOC 职业分类