Site icon saotuvi.com

Storybook là gì? Tìm hiểu công cụ Quản lý UI Component

giao diện storybook

Trong quá trình phát triển giao diện người dùng (UI) cho các dự án, việc quản lý và kiểm thử các thành phần UI một cách độc lập là một thách thức lớn. Trong các dự án lớn, sẽ phải xây dựng rất nhiều base component, khi đó bạn sẽ rất cần đến một công cụ trực quan để quản lý và thử nghiệm các thành phần một cách dễ dàng. Đây chính là lúc Storybook phát huy tác dụng.

Bài viết này mình sẽ hướng dẫn bạn chi tiết về cách cài đặt và sử dụng Storybook với React và TypeScript (các bạn hoàn toàn có thể sử dụng Storybook cho framework khác như: Vue, Angular,…), giúp bạn có thể xây dựng và quản lý các thành phần UI một cách hiệu quả.

1. Storybook là gì?

Storybook là công cụ mã nguồn mở, hỗ trợ quá trình thiết kế và phát triển các UI Component cho ứng dụng trong một môi trường biệt lập, cho phép bạn kiểm thử và xem trước các components một cách độc lập mà không cần tích hợp vào ứng dụng chính.

Mỗi component được gán một “stories”, mô tả các biến thể khác nhau của component, bao gồm tất cả các props và state có thể. Các stories giúp hiển thị trực quan cách component hoạt động trong các tình huống khác nhau, từ đó giúp quá trình phát triển dễ dàng hơn.

giao diện storybook

Bạn có thể thấy hình phía trên là cấu trúc của Storybook:

  1. Category (Danh mục): đây là mục lớn nhất, đại diện cho một hệ thống hoặc tập hợp lớn các thành phần UI có cùng một mục đích hoặc được phân nhóm chung. Ví dụ “Design System” là một danh mục.
  2. Folder (Thư mục): thường chứa các nhóm thành phần UI nhỏ hơn. Ví dụ, trong hình, “Atoms” là một thư mục, có thể chứa các thành phần UI đơn giản, nhỏ gọn.
  3. Component (Thành phần): thành phần UI cụ thể, như là một button. Trong ví dụ này, “Button” là một thành phần cụ thể nằm trong thư mục “Atoms”.
  4. Docs (Tài liệu): tài liệu mô tả hoặc giải thích về thành phần UI, cung cấp thông tin chi tiết về cách sử dụng thành phần đó. Tài liệu thường đi kèm với ví dụ về code và cách sử dụng của component.
  5. Stories (Câu chuyện): mỗi thành phần UI có thể có nhiều trạng thái khác nhau. Một stories trong Storybook là một cách để mô tả biến thể cụ thể của thành phần UI. Ví dụ, “Primary” là một stories mô tả nút ở trạng thái mặc định trong ứng dụng.

2. Tại sao nên sử dụng Storybook?

3. Ưu, nhược điểm của Storybook

3.1 Ưu điểm của Storybook

3.2 Nhược điểm của Storybook

4. Hướng dẫn sử dụng Storybook với dự án Typescript

Trước khi cài đặt Storybook, bạn cần có một project React. Nếu bạn đã có project rồi, bạn có thể bỏ qua bước này. Nếu chưa, bạn có thể tham khảo tại đây.

B1: Cài đặt Storybook

Storybook có thể được cài đặt dễ dàng bằng cách sử dụng lệnh sau:

Bash

npx storybook init

Lệnh này sẽ tự động cấu hình Storybook cho project của bạn.

Khi quá trình cài đặt hoàn tất, bạn sẽ thấy một số thay đổi trong thư mục của project:

JSON

"storybook": "storybook dev -p 6006",
"build-storybook": "storybook build"

B2: Bây giờ, bạn có thể khởi động Storybook để kiểm tra xem quá trình cài đặt đã thành công hay chưa

Bash

npm run storybook

Lệnh này sẽ khởi động Storybook trên http://localhost:6006. Khi mở trình duyệt, bạn sẽ thấy giao diện Storybook và các component mẫu.

B3: Cấu hình Typescript cho Storybook

Storybook đã hỗ trợ TypeScript ngay khi cài đặt. Tuy nhiên, để chắc chắn rằng TypeScript được cấu hình đúng, bạn có thể kiểm tra và chỉnh sửa file .storybook/main.ts như sau:

Typescript

import type { StorybookConfig } from '@storybook/react-vite'

const config: StorybookConfig = {
  stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
  addons: [
    '@storybook/addon-onboarding',
    '@storybook/addon-links',
    '@storybook/addon-essentials',
    '@chromatic-com/storybook',
    '@storybook/addon-interactions'
  ],
  framework: {
    name: '@storybook/react-vite',
    options: {}
  }
}
export default config

Mình sẽ lấy một ví dụ mà storybook mẫu cho các bạn hiểu nhé. Đây là button component

Typescript

import React from 'react';

import './button.css';

export interface ButtonProps {
  /** Is this the principal call to action on the page? */
  primary?: boolean;
  /** What background color to use */
  backgroundColor?: string;
  /** How large should the button be? */
  size?: 'small' | 'medium' | 'large';
  /** Button contents */
  label: string;
  /** Optional click handler */
  onClick?: () => void;
}

/** Primary UI component for user interaction */
export const Button = ({
  primary = false,
  size = 'medium',
  backgroundColor,
  label,
  ...props
}: ButtonProps) => {
  const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary';
  return (
    <button
      type="button"
      className={['storybook-button', `storybook-button--${size}`, mode].join(' ')}
      style={{ backgroundColor }}
      {...props}
    >
      {label}
    </button>
  );
};

Tiếp theo, khi có button component rồi, mình sẽ đi xây dựng stories cho component đó, cụ thể:

Typescript

import type { Meta, StoryObj } from '@storybook/react'
import { fn } from '@storybook/test'

import { Button } from './Button'

// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
const meta = {
  title: 'Example/Button',
  component: Button,
  parameters: {
    // Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout
    layout: 'centered'
  },
  // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
  tags: ['autodocs'],
  // More on argTypes: https://storybook.js.org/docs/api/argtypes
  argTypes: {
    backgroundColor: { control: 'color' }
  },
  // Use `fn` to spy on the onClick arg, which will appear in the actions panel once invoked: https://storybook.js.org/docs/essentials/actions#action-args
  args: { onClick: fn() }
} satisfies Meta<typeof Button>

export default meta
type Story = StoryObj<typeof meta>

// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
export const Primary: Story = {
  args: {
    primary: true,
    label: 'Button'
  }
}

export const Secondary: Story = {
  args: {
    label: 'Button'
  }
}

export const Large: Story = {
  args: {
    size: 'large',
    label: 'Button'
  }
}

export const Small: Story = {
  args: {
    size: 'small',
    label: 'Button'
  }
}

Tại sao bạn nên sử dụng args?

5. Kết luận

Qua quá trình tìm hiểu và triển khai Storybook với component Button, mình tin rằng các bạn đã nắm được những lợi ích mà storybook mang lại, cách triển khai storybook cho dự án React của bạn.

Các bài viết liên quan:

Exit mobile version