Storybook 8:组件开发 / 文档 / 视觉回归一站搞定

Storybook 是组件开发的 IDE:在隔离环境里写组件 + 各种状态展示 +
自动文档 + 视觉回归测试。Storybook 8 升级了 Vite-first / 性能大涨。

安装

npx storybook@latest init
# 自动检测项目类型(React/Vue/Svelte 等),生成 .storybook/ 配置

package.json 加 script:

{
  "scripts": {
    "storybook": "storybook dev -p 6006",
    "build-storybook": "storybook build"
  }
}

第一个 story

// src/components/Button.tsx
export function Button({ children, variant = 'primary', onClick }) {
  return <button className={`btn btn-${variant}`} onClick={onClick}>{children}</button>
}

// src/components/Button.stories.tsx
import type { Meta, StoryObj } from '@storybook/react'
import { Button } from './Button'

const meta: Meta<typeof Button> = {
  title: 'Components/Button',
  component: Button,
  tags: ['autodocs'],   // 自动生成文档页
  argTypes: {
    variant: {
      control: 'select',
      options: ['primary', 'secondary', 'danger'],
    },
    onClick: { action: 'clicked' },
  },
}
export default meta

type Story = StoryObj<typeof Button>

export const Primary: Story = {
  args: { children: 'Click me', variant: 'primary' },
}

export const Secondary: Story = {
  args: { children: 'Secondary', variant: 'secondary' },
}

export const Danger: Story = {
  args: { children: 'Delete', variant: 'danger' },
}

npm run storybook → 浏览器看到 Button 的 3 个变体 + interactive controls
可以实时改 args。

2. Controls

argTypes: {
  size: {
    control: { type: 'range', min: 12, max: 32, step: 2 },
  },
  bg: { control: 'color' },
  date: { control: 'date' },
}

Storybook UI 自动渲染滑块 / 颜色选择器 / 日期选择器。

3. 自动文档

tags: ['autodocs'] 让 Storybook 自动生成 Docs 页:

  • 组件描述(取自 JSDoc / TypeScript types)
  • Props 表格(取自 TypeScript types)
  • 所有 story 实例展示

4. MDX 写富文档

{/* src/components/Button.mdx */}

import { Canvas, Story } from '@storybook/blocks'
import * as ButtonStories from './Button.stories'

# Button

按钮组件。

## 何时使用

- 提交表单
- 触发关键操作

## 示例

<Canvas of={ButtonStories.Primary} />

注意:danger 按钮配合二次确认 modal 使用。

<Canvas of={ButtonStories.Danger} />

MDX 让你混 Markdown + 实际可交互的 story。

5. play 函数:交互测试

import { userEvent, within, expect } from '@storybook/test'

export const ClickHandling: Story = {
  args: { children: 'Click me' },
  play: async ({ canvasElement, args }) => {
    const canvas = within(canvasElement)
    const btn = canvas.getByRole('button')
    await userEvent.click(btn)
    expect(args.onClick).toHaveBeenCalled()
  },
}

打开这个 story Storybook 自动执行 play 函数 → 模拟点击 → 校验。
相当于把单元测试 + 视觉展示合一。

可以直接 npm run test-storybook 在 CI 里跑所有 play 函数。

6. decorators:包一层 context

const meta: Meta = {
  decorators: [
    (Story) => (
      <ThemeProvider theme="light">
        <div style={{ padding: 24 }}>
          <Story />
        </div>
      </ThemeProvider>
    ),
  ],
}

每个 story 自动套 Provider + 内边距。

7. globalTypes:主题 / 语言切换器

// .storybook/preview.ts
export const globalTypes = {
  theme: {
    description: '主题',
    defaultValue: 'light',
    toolbar: {
      title: 'Theme',
      icon: 'circlehollow',
      items: ['light', 'dark'],
    },
  },
}

export const decorators = [
  (Story, ctx) => (
    <ThemeProvider theme={ctx.globals.theme}>
      <Story />
    </ThemeProvider>
  ),
]

Storybook 顶部工具栏出现切换按钮,所有 story 同步主题。

8. addon:a11y / viewport / measure

npm i -D @storybook/addon-a11y @storybook/addon-viewport

.storybook/main.ts

export default {
  addons: [
    '@storybook/addon-essentials',
    '@storybook/addon-a11y',          // axe-core 自动 a11y 检查
    '@storybook/addon-viewport',      // 不同设备尺寸
  ],
}

每个 story 自动跑 a11y audit;右上角设备切换看响应式。

9. 视觉回归测试(Chromatic)

npx chromatic --project-token=xxx

Chromatic(Storybook 母公司服务)每次 build 自动截图所有 story,
和上次对比,任何视觉变化提醒你确认。

替代方案:自托管 reg-suit / loki / Percy。

10. 部署 storybook

npm run build-storybook
# 输出到 storybook-static/
# 上传任何静态托管(Vercel / Netlify / GitHub Pages / S3)

设计师 / PM / 客户能直接看组件演示。

11. 与 design token

把 Figma design tokens 导出 JSON → 写 Tailwind / Styled-Components 主题,
在 Storybook 里切换主题对比效果。Tokens Studio + Figma + Storybook 是
设计系统的成熟工作流。

12. 何时不用 Storybook

  • 小项目(< 10 个组件):维护 stories 文件成本 > 收益
  • 业务页面(不是可复用组件):直接在 app 里开发更快
  • 团队不愿意写 stories:勉强引入只会废弃

适合:组件库开发 / 设计系统 / 跨团队共享组件场景。

踩过的坑

  • Story 文件忘了 default export meta:Storybook 不识别。
  • 全局样式没在 preview.ts 里 import:story 看到的样式和 app 不一致。
    .storybook/preview.tsimport '../src/index.css'
  • Storybook 8 + Vite 5 升级有 breaking change:framework: '@storybook/react-vite'
    必须明确写。
  • Chromatic 视觉测试对小动画 / 字体渲染差异敏感,可能 false positive。
    delay: 200 等动画结束再截图。
精确评价 共 0 人评价
可复现性
可复现 · 0 不可复现 · 0
文风
文风流畅 · 0 文风晦涩 · 0
立场
支持 · 0 反对 · 0

登录后即可对本帖作出评价。

评论区 0 条 · 所有人可在此交流

登录后参与评论。

还没有评论,来说两句。