📋 目錄
元件庫最常見的問題:工程師辛苦寫了一堆元件,卻沒有人知道怎麼用——沒有文件、沒有互動預覽、不知道有哪些變體可以調整。Storybook 把元件庫變成一本可以即時互動的目錄,每個元件都有視覺化的預覽、操作說明和測試覆蓋率。
前言:為什麼 Storybook 是元件庫標配?
元件庫建立之後,最大挑戰不是「怎麼寫元件」,而是「別人怎麼知道怎麼用」。
沒有 Storybook 時,團隊成員想看某個元件長什麼樣:
- 必須把專案跑起來
- 必須找到那個元件的實際使用頁面
- 必須具備該頁面的上下文才能測試
有 Storybook 時:
- 打開瀏覽器,瀏覽所有元件目錄
- 每個元件都有獨立的展示環境
- 可以切換所有變體(variant、size、theme)
- 還能直接跑測試
Storybook 安裝
# 在現有專案加入 Storybook
npx storybook@latest init
# Storybook 會自動偵測框架(React / Vue)
# 安裝完成後啟動
npm run storybook
Storybook 預設會在 http://localhost:6006 啟動。
建立你的第一個 Story
基本 Story
// src/components/Button.stories.tsx
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';
const meta: Meta<typeof Button> = {
title: 'Form/Button', // 在 Storybook 左側選單中的路徑
component: Button,
tags: ['autodocs'], // 自動產生文件頁
argTypes: {
variant: {
control: 'select',
options: ['primary', 'secondary', 'ghost', 'danger'],
},
size: {
control: 'select',
options: ['sm', 'md', 'lg'],
},
isLoading: { control: 'boolean' },
disabled: { control: 'boolean' },
},
};
export default meta;
type Story = StoryObj<typeof meta>;
// 每個 Story 是一個變體
export const Primary: Story = {
args: {
variant: 'primary',
size: 'md',
children: '主要按鈕',
},
};
export const Secondary: Story = {
args: {
variant: 'secondary',
size: 'md',
children: '次要按鈕',
},
};
export const Loading: Story = {
args: {
variant: 'primary',
isLoading: true,
children: '載入中',
},
};
export const Disabled: Story = {
args: {
variant: 'primary',
disabled: true,
children: '無法點擊',
},
};
title 決定了左側目錄的位置:Form/Button 會出現在 Form 資料夾下的 Button。
argTypes 讓 Storybook 的 Controls panel 自動出現,團隊成員可以即時切換 props,不需要動 code 就能看到不同組合的結果。
Storybook 與 Vitest 測試整合
Storybook 可以與 Vitest 直接整合,在 Storybook 環境中跑測試:
安裝整合
npm install -D @storybook/test
把 Component Testing 加到 Story 裡
Storybook 8.x 支援在 .stories.tsx 檔案裡直接寫 Playwright 或 Vitest 測試:
// src/components/Button.stories.tsx
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';
import { within, userEvent, expect } from '@storybook/test';
const meta: Meta<typeof Button> = {
title: 'Form/Button',
component: Button,
tags: ['autodocs'],
};
export default meta;
type Story = StoryObj<typeof meta>;
export const Primary: Story = {
args: {
variant: 'primary',
size: 'md',
children: '主要按鈕',
},
};
// 在 Story 裡直接寫 Playwright 測試
export const PrimaryClick: Story = {
args: {
variant: 'primary',
size: 'md',
children: '點擊我',
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const button = canvas.getByRole('button');
await userEvent.click(button);
// 這個 Story 除了展示之外,同時也是一個 Playwright 測試
await expect(button).toHaveAttribute('data-clicked', 'true');
},
};
play 函式讓 Storybook 在 render 元件的同時執行 Playwright 測試。點擊左側的 Play 按鈕就能觸發。
在 CI 中執行 Storybook 測試
# .github/workflows/storybook.yml
name: Storybook Tests
on: [push, pull_request]
jobs:
storybook-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'
- run: npm ci
- name: Install Playwright
run: npx playwright install --with-deps
- name: Build Storybook
run: npm run build-storybook
- name: Run Storybook tests
run: npm run test-storybook
Storybook 的文档功能
Storybook 會根據你的 Story 自動產生文件:
// 加入文件說明
export const Primary: Story = {
args: {
variant: 'primary',
size: 'md',
children: '主要按鈕',
},
parameters: {
docs: {
description: {
component: '主要按鈕用於主要操作,例如送出表單、確認刪除等。<br/>**使用時機**:非最後行動作時使用。',
},
},
},
};
加上 autodocs tag 後,Storybook 會自動產生文件頁,包含:
- 元件說明
- 所有 Story 列表
- Props 表格(從 TypeScript 型別自動推斷)
- 每個 Story 的截圖
Storybook 的常見問題
Q:Storybook 和 Styleguidist 有什麼不同?
A:兩者目標類似,但 Styleguidist 已經停止維護,Storybook 是目前唯一活跃的選擇。另一個新選擇是 Ladle,比 Storybook 更輕量,構建速度更快,適合簡單的元件文件需求。
Q:Storybook 會拖慢 CI 嗎?
A:會。Storybook build 本身比較慢,建議只在 main 分支和 PR 時執行 Storybook 測試,不在每次 commit 時跑。也不要對所有元件都寫 play 測試——只針對需要互動驗證的關鍵元件。
Q:Storybook 需要對所有元件都寫 Story 嗎?
A:不需要。優先針對公開元件(要給其他團隊或其他人用的)、複雜的互動邏輯、有多個變體的元件寫 Story。內部使用的小元件不需要。
總結:元件庫的核心是文件
Storybook 的核心價值:讓元件庫從「一堆程式碼」變成「一本可以翻閱的書」。
這篇文章涵蓋:
- Storybook 的安裝與基本設定
- 建立第一個 Story(argTypes + Controls)
- Storybook + Playwright 測試整合(
play函式) - CI 中的 Storybook 測試執行
- 文件自動產生(autodocs + parameters)
下一步:在你的元件庫執行 npx storybook@latest init,選擇一個核心元件建立 Story。從 Button 或 Input 開始,看見第一個能在瀏覽器裡即時操作的文件。
想了解 Design System 的建立方式,可參考 《Design System 入門:從零開始建立你的元件庫》。