Làm ngay: Storybook chạy trong 5 phút
Nếu bạn đang có sẵn một dự án React, việc tích hợp Storybook chỉ mất vài lệnh:
cd my-react-app
npx storybook@latest init
Lệnh này tự detect React, cài dependencies và tạo ra một vài story mẫu. Sau khi xong, chạy:
npm run storybook
Mở trình duyệt tại http://localhost:6006 — bạn sẽ thấy giao diện Storybook với các component mẫu được render sẵn. Không cần chạy app chính, không cần login, không cần setup database.
Tạo story đầu tiên cho component Button. Tạo file Button.stories.jsx ngay cạnh Button.jsx:
import Button from './Button';
export default {
title: 'Components/Button',
component: Button,
};
export const Primary = {
args: {
label: 'Click me',
variant: 'primary',
},
};
export const Disabled = {
args: {
label: 'Disabled',
disabled: true,
},
};
Save file, quay lại trình duyệt — component Button xuất hiện ngay trong sidebar với 2 states: Primary và Disabled. Bạn có thể click vào từng state và chỉnh sửa props trực tiếp trên giao diện mà không cần sửa code.
Storybook giải quyết vấn đề gì?
Mình từng refactor codebase 50K lines và bài học lớn nhất là phải có test coverage tốt trước khi bắt đầu — đặc biệt là UI components. Khi refactor, bạn cần biết ngay: cái Button này có bị vỡ layout không?, cái Card component kia với dữ liệu rỗng hiển thị thế nào? Nếu phải chạy cả app lên, navigate qua 5 màn hình rồi mới thấy được component — đó là lãng phí thời gian thuần túy.
Storybook giải quyết đúng vấn đề đó: render component cô lập, không phụ thuộc vào context của app. Mỗi “story” là một trạng thái cụ thể của component. Component có 10 states → tạo 10 stories → nhìn vào Storybook là thấy hết.
Workflow trước và sau Storybook
Trước: Sửa component → chạy app → navigate đến đúng trang → kiểm tra → phát hiện lỗi → sửa → lặp lại. Mỗi vòng mất 2–3 phút.
Sau: Sửa component → Storybook auto-reload → thấy ngay. Mỗi vòng mất 5 giây.
Với team lớn hơn, Storybook còn là living documentation — designer nhìn vào Storybook thấy chính xác component đang trông như thế nào, không cần hỏi dev. QA test từng state một cách có hệ thống mà không cần setup data phức tạp.
Hiểu sâu hơn: Args, Controls và Play Functions
Args và Controls — thay đổi props ngay trên giao diện
Phần hay nhất của Storybook là Controls panel. Khi bạn định nghĩa argTypes, Storybook tự tạo UI để chỉnh sửa từng prop:
export default {
title: 'Components/Card',
component: Card,
argTypes: {
variant: {
control: { type: 'select' },
options: ['default', 'outlined', 'elevated'],
},
loading: {
control: 'boolean',
},
title: {
control: 'text',
},
},
};
Với config trên, Controls panel hiển thị dropdown cho variant, checkbox cho loading, text input cho title. Designer hay product manager có thể tự tay thử các combinations mà không cần biết code.
Play Functions — test interactions ngay trong Storybook
Từ Storybook 6.4 trở lên, bạn có thể viết interaction tests trực tiếp trong story:
import { userEvent, within } from '@storybook/testing-library';
import { expect } from '@storybook/jest';
export const FormSubmit = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
await userEvent.type(canvas.getByLabelText('Email'), '[email protected]');
await userEvent.click(canvas.getByRole('button', { name: 'Submit' }));
await expect(
canvas.getByText('Đã gửi thành công!')
).toBeInTheDocument();
},
};
Storybook chạy play function này tự động khi bạn mở story. Bạn thấy trực tiếp: form được điền, button được click, kết quả xuất hiện — tất cả chạy ngay trong Storybook mà không cần mở browser dev tools hay viết test file riêng.
Nâng cao: Addons và tích hợp CI/CD
Essential Addons nên cài ngay
Storybook có ecosystem addons phong phú. Một vài cái mình dùng thường xuyên:
- @storybook/addon-a11y — kiểm tra accessibility (WCAG) cho từng component tự động
- @storybook/addon-viewport — preview component ở các breakpoint khác nhau (mobile, tablet, desktop)
- storybook-dark-mode — toggle dark/light mode để test theme
- @storybook/addon-docs — tự động generate documentation từ JSDoc và PropTypes
Thêm addon vào .storybook/main.js:
export default {
addons: [
'@storybook/addon-essentials',
'@storybook/addon-a11y',
'storybook-dark-mode',
],
};
Chromatic — Visual Regression Testing tự động
Chromatic (do team Storybook phát triển) tích hợp với GitHub Actions để chụp snapshot từng story và so sánh với baseline. Mỗi khi có PR, Chromatic detect xem component nào bị thay đổi visual và highlight cho reviewer.
npm install chromatic --save-dev
# .github/workflows/chromatic.yml
name: Chromatic
on: push
jobs:
chromatic:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- run: npm ci
- uses: chromaui/action@v1
with:
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
Kết hợp với CI/CD pipeline, bạn có vòng feedback loop hoàn chỉnh: code push → Chromatic chụp snapshot → reviewer approve visual changes → merge. Không còn tình trạng “ủa sao cái button bị vỡ mà không ai để ý?”
Tips thực tế khi dùng Storybook
Đặt stories ngay cạnh component, không tách thư mục riêng
Đặt Button.stories.jsx cùng thư mục với Button.jsx, không phải trong một thư mục stories/ riêng biệt. Khi bạn xóa component, story file cũng bị xóa theo — không bao giờ có story “mồ côi” trỏ đến component không tồn tại.
Viết story cho edge cases — không chỉ happy path
Phần lớn bug UI xảy ra ở edge cases: text quá dài, ảnh không load, dữ liệu rỗng, lỗi network. Hãy tạo story cho những trường hợp đó:
export const LongText = {
args: {
title: 'Đây là tiêu đề rất dài dùng để test xem component có bị overflow hay bị cắt chữ không trong các viewport khác nhau',
},
};
export const EmptyState = {
args: { items: [] },
};
export const LoadingState = {
args: { loading: true },
};
Dùng Decorators để mock context một lần dùng mãi
Nhiều component cần context như Redux store, React Router, hay theme provider. Thay vì lặp lại trong từng file, khai báo global decorators trong .storybook/preview.js:
import { ThemeProvider } from './theme';
import { Provider } from 'react-redux';
import { store } from '../src/store';
export const decorators = [
(Story) => (
<Provider store={store}>
<ThemeProvider>
<Story />
</ThemeProvider>
</Provider>
),
];
Setup sớm, đừng chờ có thời gian
Storybook dễ setup nhất khi codebase còn nhỏ. Khi đã có 100 components, việc backfill stories trở nên mệt mỏi. Mình học bài này theo cách khó — sau khi refactor xong 50K lines, mới bắt đầu nghĩ đến việc document lại từng component. Mất thêm 2 tuần chỉ để viết stories cho những gì đã có sẵn.
Đặt convention ngay từ đầu: component mới phải có ít nhất 2–3 stories trước khi merge PR. Không cần hoàn hảo, nhưng phải có. Đó là cách duy nhất để Storybook thực sự có giá trị về lâu dài.

