Storybook Generator by ankish8/storybook-npm
npx skills add https://github.com/ankish8/storybook-npm --skill 'Storybook Generator'此技能遵循 myOperator UI 库中已建立的模式,为组件生成全面、一致的 Storybook 文档。
在以下情况下激活此技能:
遵循 Button 和 AlertConfiguration 组件的文档结构:
import type { Meta, StoryObj } from '@storybook/react'
import { Component } from './component'
/**
* 组件描述,包含全面的文档。
*
* ## 安装
*
* 通过 myOperator UI CLI 安装:
* ```bash
* npx myoperator-ui add component-name
* ```
*
* ## 导入
*
* ```tsx
* import { Component } from "@myoperator/ui"
* ```
*
* ## 设计令牌
*
* [设计令牌表 - 参见下方示例]
*
* ## 排版(如适用)
*
* [排版表 - 参见下方示例]
*
* ## 用法
*
* ```tsx
* <Component variant="primary" size="lg">
* Content
* </Component>
* ```
*/
const meta: Meta<typeof Component> = {
// 标题取决于组件类型和子组:
// UI 组件: 'Components/ComponentName'
// 自定义组件(无子组): 'Custom/ComponentName'
// 自定义组件(有子组): 'Custom/SubGroup/ComponentName'
title: 'Components/ComponentName',
component: Component,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
argTypes: {
variant: {
control: 'select',
options: ['default', 'primary', 'secondary'],
description: '视觉样式变体',
table: {
defaultValue: { summary: 'default' },
},
},
size: {
control: 'select',
options: ['sm', 'default', 'lg'],
description: '组件尺寸',
table: {
defaultValue: { summary: 'default' },
},
},
},
}
export default meta
type Story = StoryObj<typeof meta>
// 故事...
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
设计令牌表必须记录组件中使用的所有 CSS 变量:
## 设计令牌
| 令牌 | CSS 变量 | 用途 | 预览 |
|-------|--------------|-------|---------|
| 背景主色 | \`--semantic-bg-primary\` | 组件背景 | <div style="width: 20px; height: 20px; background: var(--semantic-bg-primary); border: 1px solid #ccc;"></div> |
| 文本主色 | \`--semantic-text-primary\` | 主要文本颜色 | <span style="color: var(--semantic-text-primary);">Aa</span> |
| 布局边框 | \`--semantic-border-layout\` | 容器边框 | <div style="width: 40px; height: 2px; background: var(--semantic-border-layout);"></div> |
从组件代码中提取 CSS 变量:
// 从此代码:
className="bg-primary text-primary-foreground border-input"
// 提取这些变量:
- --primary (bg-primary)
- --primary-foreground (text-primary-foreground)
- --input (border-input)
按用途分类:
bg-* 类text-* 类border-* 类添加适当的预览:
示例 1: Button 组件
## 设计令牌
| 令牌 | CSS 变量 | 用途 | 预览 |
|-------|--------------|-------|---------|
| 主色 | \`--primary\` | 主要按钮背景 | <div style="width: 20px; height: 20px; background: var(--primary); border-radius: 4px;"></div> |
| 主色前景 | \`--primary-foreground\` | 主要按钮上的文本 | <span style="color: var(--primary-foreground);">Aa</span> |
| 次要色 | \`--secondary\` | 次要按钮背景 | <div style="width: 20px; height: 20px; background: var(--secondary); border-radius: 4px;"></div> |
| 破坏性色 | \`--destructive\` | 破坏性按钮背景 | <div style="width: 20px; height: 20px; background: var(--destructive); border-radius: 4px;"></div> |
| 边框色 | \`--border\` | 轮廓变体边框 | <div style="width: 40px; height: 2px; background: var(--border);"></div> |
示例 2: AlertConfiguration 组件
## 设计令牌
| 令牌 | CSS 变量 | 用途 | 预览 |
|-------|--------------|-------|---------|
| 布局边框 | \`--semantic-border-layout\` | 容器边框、分隔线 | <div style="width: 40px; height: 2px; background: var(--semantic-border-layout);"></div> |
| 背景主色 | \`--semantic-bg-primary\` | 组件背景 | <div style="width: 20px; height: 20px; background: var(--semantic-bg-primary); border: 1px solid #ccc;"></div> |
| 文本主色 | \`--semantic-text-primary\` | 标签和值 | <span style="color: var(--semantic-text-primary);">Aa</span> |
| 文本弱色 | \`--semantic-text-muted\` | 描述文字 | <span style="color: var(--semantic-text-muted);">Aa</span> |
| 链接文本色 | \`--semantic-text-link\` | 充值金额(蓝色) | <span style="color: var(--semantic-text-link);">Aa</span> |
| 错误主色 | \`--semantic-error-primary\` | 负余额(红色) | <span style="color: var(--semantic-error-primary);">Aa</span> |
记录组件中文本元素的字体规范:
## 排版
| 元素 | 字体大小 | 行高 | 字重 | 字母间距 |
|---------|-----------|-------------|--------|----------------|
| 标题 | 16px (\`text-base\`) | 24px (\`leading-6\`) | 600 (\`font-semibold\`) | 0px (\`tracking-[0px]\`) |
| 副标题 | 14px (\`text-sm\`) | 20px (\`leading-5\`) | 400 (\`font-normal\`) | 0.035px (\`tracking-[0.035px]\`) |
识别文本元素:
提取 Tailwind 类:
// 从此代码:
<h3 className="text-base font-semibold tracking-[0px]">
// 提取:
- 字体大小: 16px (text-base)
- 字重: 600 (font-semibold)
- 字母间距: 0px (tracking-[0px])
映射到实际值:
text-sm = 14px
text-base = 16px
text-lg = 18px
font-normal = 400
font-medium = 500
font-semibold = 600
font-bold = 700
leading-tight = 1.25
leading-normal = 1.5
leading-relaxed = 1.625
AlertConfiguration 排版:
## 排版
| 元素 | 字体大小 | 行高 | 字重 | 字母间距 |
|---------|-----------|-------------|--------|----------------|
| 标题 | 16px (\`text-base\`) | 24px (\`leading-6\`) | 600 (\`font-semibold\`) | 0px (\`tracking-[0px]\`) |
| 描述 | 14px (\`text-sm\`) | 20px (\`leading-relaxed\`) | 400 (\`font-normal\`) | 0.035px (\`tracking-[0.035px]\`) |
| 标签 | 14px (\`text-sm\`) | 20px | 600 (\`font-semibold\`) | 0.014px (\`tracking-[0.014px]\`) |
| 值 | 14px (\`text-sm\`) | 20px | 400 (\`font-normal\`) | 0.035px (\`tracking-[0.035px]\`) |
<Component variant="primary" size="lg">
Content
</Component>
展示组合模式、受控状态、回调函数:
const [open, setOpen] = useState(false)
<Component
open={open}
onOpenChange={setOpen}
variant="primary"
onAction={handleAction}
>
<ComponentContent />
</Component>
const [value, setValue] = useState('')
<FormModal
open={isOpen}
onOpenChange={setIsOpen}
title="Edit Values"
onSave={handleSave}
>
<TextField
label="Name"
value={value}
onChange={(e) => setValue(e.target.value)}
/>
</FormModal>
为每个变体和用例创建故事:
export const Default: Story = {
args: {
children: 'Component',
},
}
export const Primary: Story = {
args: {
variant: 'primary',
children: 'Primary Component',
},
}
export const Secondary: Story = {
args: {
variant: 'secondary',
children: 'Secondary Component',
},
}
export const Destructive: Story = {
args: {
variant: 'destructive',
children: 'Destructive Component',
},
}
export const Small: Story = {
args: {
size: 'sm',
children: 'Small Component',
},
}
export const Large: Story = {
args: {
size: 'lg',
children: 'Large Component',
},
}
export const WithState: Story = {
render: () => {
const [open, setOpen] = React.useState(false)
return (
<>
<Button onClick={() => setOpen(true)}>
Open Component
</Button>
<Component
open={open}
onOpenChange={setOpen}
/>
</>
)
},
}
export const AllVariants: Story = {
render: () => (
<div className="flex flex-col gap-4">
<div className="flex gap-2">
<Component variant="default">Default</Component>
<Component variant="primary">Primary</Component>
<Component variant="secondary">Secondary</Component>
</div>
<div className="flex gap-2">
<Component size="sm">Small</Component>
<Component size="default">Default</Component>
<Component size="lg">Large</Component>
</div>
</div>
),
}
export const States: Story = {
render: () => (
<div className="flex flex-col gap-4">
<Component>Normal</Component>
<Component disabled>Disabled</Component>
<Component loading>Loading</Component>
</div>
),
}
如果组件有来自第 2 阶段的状态清单表,则为每个视觉状态创建一个故事:
// 示例:WalletTopup 有默认、未预选、加载中和禁用状态
export const Default: Story = {
args: {
amounts: [100, 200, 500],
selectedAmount: 100,
},
}
export const NoPreselection: Story = {
args: {
amounts: [100, 200, 500],
// 无 selectedAmount — 测试空/初始状态
},
}
export const Loading: Story = {
args: {
amounts: [100, 200, 500],
isLoading: true,
},
}
export const Disabled: Story = {
args: {
amounts: [100, 200, 500],
disabled: true,
},
}
多状态故事的规则:
Success、Error、Empty)render 函数对于具有领域特定属性(在第 5 阶段第 1e 步中确认)的组件,创建展示关键属性组合的故事:
// 示例:WalletTopup 有 currency、voucherLink、amounts、headerIcon
export const DollarCurrency: Story = {
args: {
currency: '$',
amounts: [10, 25, 50, 100],
},
}
export const CustomVoucherIcon: Story = {
args: {
amounts: [100, 200, 500],
headerIcon: <Gift className="h-5 w-5" />,
},
}
export const NoVoucherLink: Story = {
args: {
amounts: [100, 200, 500],
showVoucherLink: false,
},
}
领域特定属性故事的规则:
记录所有属性,包含描述和控制选项:
argTypes: {
variant: {
control: 'select',
options: ['default', 'primary', 'secondary', 'destructive'],
description: '组件的视觉样式变体',
table: {
defaultValue: { summary: 'default' },
type: { summary: 'string' },
},
},
size: {
control: 'select',
options: ['sm', 'default', 'lg', 'xl'],
description: '组件尺寸',
table: {
defaultValue: { summary: 'default' },
type: { summary: 'string' },
},
},
disabled: {
control: 'boolean',
description: '禁用组件交互',
table: {
defaultValue: { summary: false },
type: { summary: 'boolean' },
},
},
loading: {
control: 'boolean',
description: '显示加载状态',
table: {
defaultValue: { summary: false },
type: { summary: 'boolean' },
},
},
onAction: {
action: 'clicked',
description: '触发操作时的回调函数',
table: {
type: { summary: '() => void' },
},
},
}
对于具有领域特定属性的组件,记录所有三个类别:
argTypes: {
// 数据属性
amounts: {
control: 'object',
description: '要显示的预设金额数组',
table: {
type: { summary: 'number[]' },
defaultValue: { summary: '[100, 200, 500, 1000]' },
},
},
currency: {
control: 'text',
description: '要显示的货币符号',
table: {
type: { summary: 'string' },
defaultValue: { summary: '₹' },
},
},
// 回调属性
onSubmit: {
action: 'submitted',
description: '用户提交所选/输入金额时调用',
table: {
type: { summary: '(amount: number) => void' },
},
},
// 自定义属性
headerIcon: {
control: false,
description: '标题的自定义图标。默认为 Wallet 图标。',
table: {
type: { summary: 'React.ReactNode' },
},
},
}
Button 组件故事:
import type { Meta, StoryObj } from '@storybook/react'
import { Button } from './button'
import { Loader2, Plus } from 'lucide-react'
/**
* 一个可自定义的按钮组件,支持多种变体、尺寸和图标。
*
* ## 安装
*
* 通过 myOperator UI CLI 安装:
* ```bash
* npx myoperator-ui add button
* ```
*
* ## 导入
*
* ```tsx
* import { Button } from "@myoperator/ui"
* ```
*
* ## 设计令牌
*
* | 令牌 | CSS 变量 | 用途 | 预览 |
* |-------|--------------|-------|---------|
* | 主色 | \`--primary\` | 主要按钮背景 | <div style="width: 20px; height: 20px; background: var(--primary); border-radius: 4px;"></div> |
* | 主色前景 | \`--primary-foreground\` | 主要按钮上的文本 | <span style="color: var(--primary-foreground);">Aa</span> |
* | 次要色 | \`--secondary\` | 次要按钮背景 | <div style="width: 20px; height: 20px; background: var(--secondary); border-radius: 4px;"></div> |
* | 破坏性色 | \`--destructive\` | 破坏性操作背景 | <div style="width: 20px; height: 20px; background: var(--destructive); border-radius: 4px;"></div> |
* | 边框色 | \`--border\` | 轮廓变体边框 | <div style="width: 40px; height: 2px; background: var(--border);"></div> |
*
* ## 用法
*
* ```tsx
* // 基本用法
* <Button variant="primary" size="lg">
* Click me
* </Button>
*
* // 带图标
* <Button variant="default" leftIcon={<Plus />}>
* Add Item
* </Button>
*
* // 加载状态
* <Button variant="primary" loading>
* Saving...
* </Button>
* ```
*/
const meta: Meta<typeof Button> = {
title: 'Components/Button',
component: Button,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
argTypes: {
variant: {
control: 'select',
options: ['default', 'primary', 'secondary', 'destructive', 'outline', 'ghost', 'link'],
description: '视觉样式变体',
table: {
defaultValue: { summary: 'default' },
},
},
size: {
control: 'select',
options: ['default', 'sm', 'lg', 'icon'],
description: '按钮尺寸',
table: {
defaultValue: { summary: 'default' },
},
},
loading: {
control: 'boolean',
description: '显示加载旋转器',
},
disabled: {
control: 'boolean',
description: '禁用按钮交互',
},
},
}
export default meta
type Story = StoryObj<typeof meta>
export const Default: Story = {
args: {
children: 'Button',
},
}
export const Primary: Story = {
args: {
variant: 'primary',
children: 'Primary Button',
},
}
export const AllVariants: Story = {
render: () => (
<div className="flex flex-wrap gap-4">
<Button variant="default">Default</Button>
<Button variant="primary">Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="destructive">Destructive</Button>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="link">Link</Button>
</div>
),
}
export const WithIcons: Story = {
render: () => (
<div className="flex flex-wrap gap-4">
<Button leftIcon={<Plus className="h-4 w-4" />}>
Add Item
</Button>
<Button variant="primary" rightIcon={<Plus className="h-4 w-4" />}>
Add Item
</Button>
</div>
),
}
export const Loading: Story = {
render: () => (
<div className="flex flex-wrap gap-4">
<Button loading>Loading</Button>
<Button variant="primary" loading>
Saving...
</Button>
</div>
),
}
在最终确定文档之前:
在组件完全实现后(第 5 阶段完成),重新检查:
Components/Name,自定义组件为 Custom/Name 或 Custom/SubGroup/Name)此技能确保生成全面、一致的文档,帮助用户有效理解和使用组件。
每周安装
0
仓库
GitHub 星标
1
首次出现
1970年1月1日
安全审计
This skill generates comprehensive, consistent Storybook documentation for components following established patterns in the myOperator UI library.
Activate this skill when:
Follow the Button and AlertConfiguration component documentation structure:
import type { Meta, StoryObj } from '@storybook/react'
import { Component } from './component'
/**
* Component description with comprehensive documentation.
*
* ## Installation
*
* Install via the myOperator UI CLI:
* ```bash
* npx myoperator-ui add component-name
* ```
*
* ## Import
*
* ```tsx
* import { Component } from "@myoperator/ui"
* ```
*
* ## Design Tokens
*
* [Design tokens table - see examples below]
*
* ## Typography (if applicable)
*
* [Typography table - see examples below]
*
* ## Usage
*
* ```tsx
* <Component variant="primary" size="lg">
* Content
* </Component>
* ```
*/
const meta: Meta<typeof Component> = {
// Title depends on component type and sub-group:
// UI component: 'Components/ComponentName'
// Custom (no sub-group): 'Custom/ComponentName'
// Custom (with sub-group): 'Custom/SubGroup/ComponentName'
title: 'Components/ComponentName',
component: Component,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
argTypes: {
variant: {
control: 'select',
options: ['default', 'primary', 'secondary'],
description: 'Visual style variant',
table: {
defaultValue: { summary: 'default' },
},
},
size: {
control: 'select',
options: ['sm', 'default', 'lg'],
description: 'Size of the component',
table: {
defaultValue: { summary: 'default' },
},
},
},
}
export default meta
type Story = StoryObj<typeof meta>
// Stories...
The design tokens table must document all CSS variables used in the component:
## Design Tokens
| Token | CSS Variable | Usage | Preview |
|-------|--------------|-------|---------|
| Background Primary | \`--semantic-bg-primary\` | Component background | <div style="width: 20px; height: 20px; background: var(--semantic-bg-primary); border: 1px solid #ccc;"></div> |
| Text Primary | \`--semantic-text-primary\` | Primary text color | <span style="color: var(--semantic-text-primary);">Aa</span> |
| Border Layout | \`--semantic-border-layout\` | Container borders | <div style="width: 40px; height: 2px; background: var(--semantic-border-layout);"></div> |
Extract CSS variables from component code :
// From this code:
className="bg-primary text-primary-foreground border-input"
// Extract these variables:
- --primary (bg-primary)
- --primary-foreground (text-primary-foreground)
- --input (border-input)
Categorize by usage :
bg-* classestext-* classesborder-* classesAdd appropriate preview :
Example 1: Button Component
## Design Tokens
| Token | CSS Variable | Usage | Preview |
|-------|--------------|-------|---------|
| Primary | \`--primary\` | Primary button background | <div style="width: 20px; height: 20px; background: var(--primary); border-radius: 4px;"></div> |
| Primary Foreground | \`--primary-foreground\` | Text on primary button | <span style="color: var(--primary-foreground);">Aa</span> |
| Secondary | \`--secondary\` | Secondary button background | <div style="width: 20px; height: 20px; background: var(--secondary); border-radius: 4px;"></div> |
| Destructive | \`--destructive\` | Destructive button background | <div style="width: 20px; height: 20px; background: var(--destructive); border-radius: 4px;"></div> |
| Border | \`--border\` | Outline variant border | <div style="width: 40px; height: 2px; background: var(--border);"></div> |
Example 2: AlertConfiguration Component
## Design Tokens
| Token | CSS Variable | Usage | Preview |
|-------|--------------|-------|---------|
| Border Layout | \`--semantic-border-layout\` | Container border, dividers | <div style="width: 40px; height: 2px; background: var(--semantic-border-layout);"></div> |
| Background Primary | \`--semantic-bg-primary\` | Component background | <div style="width: 20px; height: 20px; background: var(--semantic-bg-primary); border: 1px solid #ccc;"></div> |
| Text Primary | \`--semantic-text-primary\` | Labels and values | <span style="color: var(--semantic-text-primary);">Aa</span> |
| Text Muted | \`--semantic-text-muted\` | Descriptions | <span style="color: var(--semantic-text-muted);">Aa</span> |
| Text Link | \`--semantic-text-link\` | Top-up amount (blue) | <span style="color: var(--semantic-text-link);">Aa</span> |
| Error Primary | \`--semantic-error-primary\` | Negative balance (red) | <span style="color: var(--semantic-error-primary);">Aa</span> |
Document font specifications for text elements in the component:
## Typography
| Element | Font Size | Line Height | Weight | Letter Spacing |
|---------|-----------|-------------|--------|----------------|
| Title | 16px (\`text-base\`) | 24px (\`leading-6\`) | 600 (\`font-semibold\`) | 0px (\`tracking-[0px]\`) |
| Subtitle | 14px (\`text-sm\`) | 20px (\`leading-5\`) | 400 (\`font-normal\`) | 0.035px (\`tracking-[0.035px]\`) |
Identify text elements :
Extract Tailwind classes :
// From this code:
<h3 className="text-base font-semibold tracking-[0px]">
// Extract:
- Font Size: 16px (text-base)
- Weight: 600 (font-semibold)
- Letter Spacing: 0px (tracking-[0px])
Map to actual values :
text-sm = 14px
text-base = 16px
text-lg = 18px
font-normal = 400
font-medium = 500
font-semibold = 600
font-bold = 700
leading-tight = 1.25
leading-normal = 1.5
leading-relaxed = 1.625
AlertConfiguration Typography:
## Typography
| Element | Font Size | Line Height | Weight | Letter Spacing |
|---------|-----------|-------------|--------|----------------|
| Title | 16px (\`text-base\`) | 24px (\`leading-6\`) | 600 (\`font-semibold\`) | 0px (\`tracking-[0px]\`) |
| Description | 14px (\`text-sm\`) | 20px (\`leading-relaxed\`) | 400 (\`font-normal\`) | 0.035px (\`tracking-[0.035px]\`) |
| Label | 14px (\`text-sm\`) | 20px | 600 (\`font-semibold\`) | 0.014px (\`tracking-[0.014px]\`) |
| Value | 14px (\`text-sm\`) | 20px | 400 (\`font-normal\`) | 0.035px (\`tracking-[0.035px]\`) |
<Component variant="primary" size="lg">
Content
</Component>
Show composition patterns, controlled state, callbacks:
const [open, setOpen] = useState(false)
<Component
open={open}
onOpenChange={setOpen}
variant="primary"
onAction={handleAction}
>
<ComponentContent />
</Component>
const [value, setValue] = useState('')
<FormModal
open={isOpen}
onOpenChange={setIsOpen}
title="Edit Values"
onSave={handleSave}
>
<TextField
label="Name"
value={value}
onChange={(e) => setValue(e.target.value)}
/>
</FormModal>
Create stories for each variant and use case:
export const Default: Story = {
args: {
children: 'Component',
},
}
export const Primary: Story = {
args: {
variant: 'primary',
children: 'Primary Component',
},
}
export const Secondary: Story = {
args: {
variant: 'secondary',
children: 'Secondary Component',
},
}
export const Destructive: Story = {
args: {
variant: 'destructive',
children: 'Destructive Component',
},
}
export const Small: Story = {
args: {
size: 'sm',
children: 'Small Component',
},
}
export const Large: Story = {
args: {
size: 'lg',
children: 'Large Component',
},
}
export const WithState: Story = {
render: () => {
const [open, setOpen] = React.useState(false)
return (
<>
<Button onClick={() => setOpen(true)}>
Open Component
</Button>
<Component
open={open}
onOpenChange={setOpen}
/>
</>
)
},
}
export const AllVariants: Story = {
render: () => (
<div className="flex flex-col gap-4">
<div className="flex gap-2">
<Component variant="default">Default</Component>
<Component variant="primary">Primary</Component>
<Component variant="secondary">Secondary</Component>
</div>
<div className="flex gap-2">
<Component size="sm">Small</Component>
<Component size="default">Default</Component>
<Component size="lg">Large</Component>
</div>
</div>
),
}
export const States: Story = {
render: () => (
<div className="flex flex-col gap-4">
<Component>Normal</Component>
<Component disabled>Disabled</Component>
<Component loading>Loading</Component>
</div>
),
}
If the component has a State Inventory Table from Phase 2, create a story for each visual state :
// Example: WalletTopup has Default, No Preselection, Loading, and Disabled states
export const Default: Story = {
args: {
amounts: [100, 200, 500],
selectedAmount: 100,
},
}
export const NoPreselection: Story = {
args: {
amounts: [100, 200, 500],
// no selectedAmount — tests empty/initial state
},
}
export const Loading: Story = {
args: {
amounts: [100, 200, 500],
isLoading: true,
},
}
export const Disabled: Story = {
args: {
amounts: [100, 200, 500],
disabled: true,
},
}
Rules for multi-state stories:
Success, Error, Empty)render with internal stateFor components with domain-specific props (confirmed in Phase 5, Step 1e), create stories demonstrating key prop combinations:
// Example: WalletTopup has currency, voucherLink, amounts, headerIcon
export const DollarCurrency: Story = {
args: {
currency: '$',
amounts: [10, 25, 50, 100],
},
}
export const CustomVoucherIcon: Story = {
args: {
amounts: [100, 200, 500],
headerIcon: <Gift className="h-5 w-5" />,
},
}
export const NoVoucherLink: Story = {
args: {
amounts: [100, 200, 500],
showVoucherLink: false,
},
}
Rules for domain-specific prop stories:
Document all props with descriptions and controls:
argTypes: {
variant: {
control: 'select',
options: ['default', 'primary', 'secondary', 'destructive'],
description: 'Visual style variant of the component',
table: {
defaultValue: { summary: 'default' },
type: { summary: 'string' },
},
},
size: {
control: 'select',
options: ['sm', 'default', 'lg', 'xl'],
description: 'Size of the component',
table: {
defaultValue: { summary: 'default' },
type: { summary: 'string' },
},
},
disabled: {
control: 'boolean',
description: 'Disables the component interaction',
table: {
defaultValue: { summary: false },
type: { summary: 'boolean' },
},
},
loading: {
control: 'boolean',
description: 'Shows loading state',
table: {
defaultValue: { summary: false },
type: { summary: 'boolean' },
},
},
onAction: {
action: 'clicked',
description: 'Callback when action is triggered',
table: {
type: { summary: '() => void' },
},
},
}
For components with domain-specific props, document all three categories:
argTypes: {
// Data props
amounts: {
control: 'object',
description: 'Array of preset amounts to display',
table: {
type: { summary: 'number[]' },
defaultValue: { summary: '[100, 200, 500, 1000]' },
},
},
currency: {
control: 'text',
description: 'Currency symbol to display',
table: {
type: { summary: 'string' },
defaultValue: { summary: '₹' },
},
},
// Callback props
onSubmit: {
action: 'submitted',
description: 'Called when user submits with the selected/entered amount',
table: {
type: { summary: '(amount: number) => void' },
},
},
// Customization props
headerIcon: {
control: false,
description: 'Custom icon for the header. Defaults to Wallet icon.',
table: {
type: { summary: 'React.ReactNode' },
},
},
}
Button Component Story:
import type { Meta, StoryObj } from '@storybook/react'
import { Button } from './button'
import { Loader2, Plus } from 'lucide-react'
/**
* A customizable button component with multiple variants, sizes, and icon support.
*
* ## Installation
*
* Install via the myOperator UI CLI:
* ```bash
* npx myoperator-ui add button
* ```
*
* ## Import
*
* ```tsx
* import { Button } from "@myoperator/ui"
* ```
*
* ## Design Tokens
*
* | Token | CSS Variable | Usage | Preview |
* |-------|--------------|-------|---------|
* | Primary | \`--primary\` | Primary button background | <div style="width: 20px; height: 20px; background: var(--primary); border-radius: 4px;"></div> |
* | Primary Foreground | \`--primary-foreground\` | Text on primary button | <span style="color: var(--primary-foreground);">Aa</span> |
* | Secondary | \`--secondary\` | Secondary button background | <div style="width: 20px; height: 20px; background: var(--secondary); border-radius: 4px;"></div> |
* | Destructive | \`--destructive\` | Destructive action background | <div style="width: 20px; height: 20px; background: var(--destructive); border-radius: 4px;"></div> |
* | Border | \`--border\` | Outline variant border | <div style="width: 40px; height: 2px; background: var(--border);"></div> |
*
* ## Usage
*
* ```tsx
* // Basic usage
* <Button variant="primary" size="lg">
* Click me
* </Button>
*
* // With icons
* <Button variant="default" leftIcon={<Plus />}>
* Add Item
* </Button>
*
* // Loading state
* <Button variant="primary" loading>
* Saving...
* </Button>
* ```
*/
const meta: Meta<typeof Button> = {
title: 'Components/Button',
component: Button,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
argTypes: {
variant: {
control: 'select',
options: ['default', 'primary', 'secondary', 'destructive', 'outline', 'ghost', 'link'],
description: 'Visual style variant',
table: {
defaultValue: { summary: 'default' },
},
},
size: {
control: 'select',
options: ['default', 'sm', 'lg', 'icon'],
description: 'Button size',
table: {
defaultValue: { summary: 'default' },
},
},
loading: {
control: 'boolean',
description: 'Shows loading spinner',
},
disabled: {
control: 'boolean',
description: 'Disables button interaction',
},
},
}
export default meta
type Story = StoryObj<typeof meta>
export const Default: Story = {
args: {
children: 'Button',
},
}
export const Primary: Story = {
args: {
variant: 'primary',
children: 'Primary Button',
},
}
export const AllVariants: Story = {
render: () => (
<div className="flex flex-wrap gap-4">
<Button variant="default">Default</Button>
<Button variant="primary">Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="destructive">Destructive</Button>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="link">Link</Button>
</div>
),
}
export const WithIcons: Story = {
render: () => (
<div className="flex flex-wrap gap-4">
<Button leftIcon={<Plus className="h-4 w-4" />}>
Add Item
</Button>
<Button variant="primary" rightIcon={<Plus className="h-4 w-4" />}>
Add Item
</Button>
</div>
),
}
export const Loading: Story = {
render: () => (
<div className="flex flex-wrap gap-4">
<Button loading>Loading</Button>
<Button variant="primary" loading>
Saving...
</Button>
</div>
),
}
Before finalizing documentation:
After the component is fully implemented (Phase 5 complete), re-check:
Components/Name for UI, Custom/Name or Custom/SubGroup/Name for custom)This skill ensures comprehensive, consistent documentation that helps users understand and use components effectively.
Weekly Installs
0
Repository
GitHub Stars
1
First Seen
Jan 1, 1970
Security Audits
agent-browser 浏览器自动化工具 - Vercel Labs 命令行网页操作与测试
138,300 周安装
Gmail 收件箱快速处理工具 - gws-gmail-triage 命令使用指南 | Google Workspace CLI
9,500 周安装
GWS Gmail 发送邮件命令:通过命令行快速发送Gmail邮件(支持附件、HTML、草稿)
9,400 周安装
FastAPI项目模板:生产就绪的异步REST API与微服务开发最佳实践
9,500 周安装
NestJS最佳实践指南:40条规则提升架构、性能与安全性
9,500 周安装
Google Workspace CLI 日历议程:快速查看即将发生的事件,支持筛选和时区设置
9,800 周安装
Spring Boot 最佳实践指南:项目结构、依赖注入、配置、Web层与安全
9,900 周安装