Storybook үндэс
Storybook бол UI component-уудыг бүтэн аппаас тусдаа харж, тест хийх, баримтжуулах тусгай орчин юм. Апп-г ажиллуулахгүйгээр component-оо бүх "хэлбэр"-ээр нь харж болдог — жишээ нь Button component-н primary, disabled, loading гэсэн бүх төлвийг тусдаа харуулна. Facebook, Airbnb, GitHub зэрэг компаниуд дизайн систем бүтээхдээ Storybook ашигладаг.
Яагаад Storybook хэрэгтэй вэ?
Component-ыг аппын гүнд байрлуулаагүй бол туршихад хэцүү байдаг. Жишээ нь Button component-н disabled + loading төлвийг нэгэн зэрэг харахын тулд тусгай дэлгэц гаргах шаардлагатай болдог.
Storybook-тэй бол:
src/components/Button/
├── Button.tsx ← component
└── Button.stories.tsx ← бүх "хэлбэр" тодорхойлсон story файл
Button.stories.tsx нээхэд браузерт Primary, Secondary, Disabled, Loading гэсэн бүх төлвийг хажуу хажуугаар харж болно — апп ажиллуулах шаардлагагүй.
Storybook суулгах
npx storybook@latest init
Vite + React аппыг автоматаар таньж тохируулна. Суусны дараа:
npm run storybook
http://localhost:6006 хаягаар Storybook нээгдэнэ. src/stories/ хавтаст жишээ story-нууд байгааг харна — тэдгээрийг ажиглаад эхэлж болно.
Анхны Story бичих
Button component-н story:
// src/components/Button/Button.stories.tsx
import type { Meta, StoryObj } from "@storybook/react";
import Button from "./Button";
// Файлын мета мэдээлэл — Storybook-д хэрхэн харагдахыг тодорхойлно
const meta: Meta<typeof Button> = {
title: "UI/Button", // Storybook sidebar-д байрлах зам
component: Button,
tags: ["autodocs"], // Props-ыг автоматаар баримтжуулна
args: {
// Бүх story-д нийтлэг default утгууд
onClick: () => {},
},
};
export default meta;
type Story = StoryObj<typeof Button>;
// Тус тус story — component-н нэг "хэлбэр"
export const Primary: Story = {
args: {
label: "Эхлэх",
variant: "primary",
},
};
export const Secondary: Story = {
args: {
label: "Болих",
variant: "secondary",
},
};
export const Disabled: Story = {
args: {
label: "Идэвхгүй",
variant: "primary",
disabled: true,
},
};
export const Loading: Story = {
args: {
label: "Хадгалж байна...",
variant: "primary",
isLoading: true,
},
};
export const AllVariants: Story = {
render: () => (
<div style={{ display: "flex", gap: 12 }}>
<Button label="Primary" variant="primary" />
<Button label="Secondary" variant="secondary" />
<Button label="Danger" variant="danger" />
</div>
),
};
Нарийн component-н Story
Илүү олон props-тэй CourseCard component-н story:
// src/components/CourseCard/CourseCard.stories.tsx
import type { Meta, StoryObj } from "@storybook/react";
import CourseCard from "./CourseCard";
const meta: Meta<typeof CourseCard> = {
title: "Course/CourseCard",
component: CourseCard,
tags: ["autodocs"],
parameters: {
// Story-г хэрхэн харуулах — centered: дунд байрлуулна
layout: "centered",
},
};
export default meta;
type Story = StoryObj<typeof CourseCard>;
export const Free: Story = {
args: {
title: "JavaScript үндэс",
lessonCount: 20,
color: "green",
isFree: true,
courseNum: "01",
onEnroll: () => alert("Бүртгүүллээ!"),
},
};
export const Pro: Story = {
args: {
title: "React үндэс",
lessonCount: 45,
color: "blue",
isFree: false,
courseNum: "04",
onEnroll: () => {},
},
};
export const WithProgress: Story = {
args: {
...Pro.args,
completedCount: 18,
},
};
// Бүх курсийн өнгийг нэг дор харуулах
export const AllColors: Story = {
render: () => (
<div
style={{
display: "grid",
gridTemplateColumns: "repeat(3, 300px)",
gap: 16,
}}
>
{[
{ title: "JavaScript", color: "green", num: "01" },
{ title: "TypeScript", color: "purple", num: "02" },
{ title: "React", color: "blue", num: "04" },
{ title: "Next.js", color: "indigo", num: "05" },
{ title: "Go", color: "teal", num: "07" },
{ title: "Python", color: "amber", num: "03" },
].map((c) => (
<CourseCard
key={c.num}
title={c.title}
color={c.color}
courseNum={c.num}
lessonCount={20}
isFree={false}
onEnroll={() => {}}
/>
))}
</div>
),
};
Storybook-д Provider нэмэх
Context ашигладаг component-ыг Story-д ажиллуулахын тулд Provider-г .storybook/preview.tsx-д нэмнэ:
// .storybook/preview.tsx
import type { Preview } from "@storybook/react";
import { ThemeProvider } from "../src/contexts/ThemeContext";
import "../src/app/globals.css";
const preview: Preview = {
decorators: [
// Бүх story-г ThemeProvider-д боодог
(Story) => (
<ThemeProvider>
<Story />
</ThemeProvider>
),
],
parameters: {
backgrounds: {
default: "dark",
values: [
{ name: "dark", value: "#0b1120" },
{ name: "light", value: "#ffffff" },
],
},
},
};
export default preview;
Storybook нь зөвхөн том компаниудад хэрэгтэй юм биш — нэг хөгжүүлэгч ч component-оо цэгцтэй хадгалах, хуучин харагдах байдлыг дурдахад маш хэрэгтэй. Курс энд дуусахад Storybook нэмж апп-аа бүрэн дүүрэн болгохыг зөвлөж байна.
Дараагийн хичээлд:
Эцсийн төсөл — курсын туршид сурсан бүх ойлголтоо нэгтгэсэн бодит React апп бүтээнэ. Component-уудыг бичих, state удирдах, TypeScript хэрэглэх, тест бичих — бүгдийг нэг дор хэрэглэх цаг боллоо.