اخبار وب

Storybook 9 و توسعه کامپوننت‌محور

ساخت Storyهای حالت عادی، busy و disabled برای دکمه React، تفاوت Args و Controls و محدوده بررسی Visual و Interaction در Storybook 9.

1404/12/25 2 دقیقه مطالعه 1,280 بازدید
Storybook 9 و توسعه کامپوننت‌محور

Storybook محیطی برای دیدن componentها در حالت‌های مشخص، بیرون از صفحه کامل محصول است. اگر یک دکمه در حالت عادی، غیرفعال و در حال ارسال رفتار متفاوتی دارد، می‌توانید هر حالت را با داده صریح نشان دهید. این کار به طراحی و مرور کمک می‌کند، ولی به معنی اثبات سلامت کل مسیر خرید یا ورود نیست. component هنوز باید در صفحه واقعی، با داده و قرارداد عمل مناسب ترکیب شود.

Storybook 9 در ژوئن ۲۰۲۵ با تمرکز بر گردش کار توسعه و بررسی component معرفی شد. اعلام رسمی نسخه 9 ویژگی‌های انتشار را شرح می‌دهد. درصد سرعت بدون روش اندازه‌گیری که در نسخه قبلی این مقاله آمده بود حذف شده است. این مطلب درباره استفاده از همان خانواده نسخه است؛ پروژه تازه باید نسخه و integration پشتیبانی‌شده مناسب framework خود را انتخاب کند.

Story قرارداد حالت است

یک Story باید حالت قابل توضیحی را نمایش دهد. نام «دکمه قرمز» فقط ظاهر را می‌گوید؛ نام «در حال ارسال» رفتار و هدف را روشن‌تر می‌کند. اگر داده نمونه وضعیت غیرممکنی می‌سازد، حتی یک Story زیبا هم گمراه‌کننده است. برای مثال، عمل ارسال نباید هم‌زمان فعال و دارای برچسب موفقیت نهایی باشد مگر محصول چنین رفتار تعریف‌شده‌ای داشته باشد.

برای هر component، حالت‌های واقعی مصرف‌کننده را بنویسید. یک ورودی ممکن است مقدار خالی، مقدار معتبر، خطا و حالت readonly داشته باشد. این حالت‌ها از منطق محصول می‌آیند و لازم نیست همه با یک آرایه طولانی props ساخته شوند. اگر ترکیب propsهای موجود به حالت متناقض می‌رسد، خود API component به بازبینی نیاز دارد.

Story به تیم کمک می‌کند همان component را با داده مشخص مرور کند. طراحی نباید فقط به screenshot حالت عادی محدود بماند. عنوان بلند فارسی، viewport کوچک و متن دکمه چندکلمه‌ای می‌توانند مسئله‌ای را آشکار کنند که در داده کوتاه انگلیسی دیده نمی‌شود. داده نمونه را با مخاطب محصول هماهنگ کنید و اطلاعات شخصی واقعی مشتری را وارد مستند عمومی نکنید.

Props، Args و Controls را هم‌معنا فرض نکنید

Props قرارداد component است؛ Args مقدارهای مورد استفاده Story را بیان می‌کند و Controls رابطی برای تغییر بعضی از این مقدارها در محیط مرور فراهم می‌کند. راهنمای Writing stories و راهنمای Controls این رابطه را توضیح می‌دهند. وجود یک control نباید نوع یا معنای prop را عوض کند.

Controls برای کشف حالت‌ها مفید است، ولی هر ترکیب موقتی را مستند رسمی محصول نکنید. Story نام‌گذاری‌شده می‌تواند یک حالت مورد توافق باشد و کنترل آزاد فقط ابزار مرور. این تفاوت به تیم طراحی کمک می‌کند بداند کدام تصویر، نمونه تأییدشده است و کدام نتیجه آزمایش گزینه‌ها. نمایش اتفاقی یک ترکیب نباید به قرارداد پشتیبانی آن تبدیل شود.

اگر component به context، theme یا provider نیاز دارد، محیط Story باید این وابستگی را صریح فراهم کند. حذف provider فقط برای اینکه نمونه ساده باز شود، رفتار واقعی را پنهان می‌کند. در مقابل، اتصال به تمام backend Production برای نمایش یک دکمه هم ضرورت ندارد. قرارداد حداقلی اما واقعی محیط، نقطه مناسب ساخت مستند است.

نمونه یک دکمه با سه حالت روشن

برای نمونه مستقل، ابتدا یک پروژه React و TypeScript با Vite سازگار بسازید. سپس با فرمان npm create storybook@9 و گزینه integration مربوط به React و Vite، Storybook خانواده 9 را اضافه کنید. CLI فایل‌های تنظیم لازم را می‌سازد؛ نام packageها را مطابق نتیجه همان نصب نگه دارید و نسخه‌های major مختلف را بی‌بررسی ترکیب نکنید. راهنمای Configure مرجع تنظیم پروژه است.

فایل src/SubmitButton.tsx زیر component کامل نمونه است. busy و disabled دو علت غیرفعال بودن دکمه را بیان می‌کنند. در حالت busy متن تغییر می‌کند و دکمه دوباره عمل را آغاز نمی‌کند. onClick از مصرف‌کننده می‌آید؛ این component خودش درخواست شبکه نمی‌فرستد و نتیجه کسب‌وکار را نگه نمی‌دارد. بنابراین وضعیت ارسال باید در والد مدیریت شود.

import type { MouseEventHandler } from "react";
import "./SubmitButton.css";

export interface SubmitButtonProps {
  label: string;
  busy?: boolean;
  disabled?: boolean;
  onClick?: MouseEventHandler<HTMLButtonElement>;
}
export function SubmitButton({ label, busy = false, disabled = false, onClick }: SubmitButtonProps) {
  return <button className="submit-button" type="button" disabled={disabled || busy} aria-busy={busy} onClick={onClick}>
    {busy ? "در حال ارسال…" : label}
  </button>;
}

CSS زیر را با نام src/SubmitButton.css ذخیره کنید. component همین فایل را import می‌کند، پس style معرفی‌نشده‌ای لازم نیست. کلاس submit-button در markup وجود دارد و قواعد focus-visible و disabled به کنترل واقعی تعلق دارند. رنگ‌ها انتخاب آموزشی‌اند و باید با theme محصول هماهنگ شوند؛ این نمونه یک Design System کامل نیست.

.submit-button { font: inherit; padding: .65rem 1rem; color: white; background: #174c87; border: 1px solid #174c87; border-radius: .4rem; cursor: pointer; }
.submit-button:disabled { background: #596979; border-color: #596979; cursor: default; }
.submit-button:focus-visible { outline: 3px solid #174c87; outline-offset: 3px; }

فایل src/SubmitButton.stories.tsx سه Story دارد. هر کدام ترکیب قابل فهمی از args را استفاده می‌کند. fn برای ثبت callback در محیط Story آمده است و اثبات موفقیت ارسال نیست. هیچ API واقعی یا token لازم نداریم. meta نوع component را نگه می‌دارد و نام مجموعه، مسیر آن را در محیط مرور مشخص می‌کند.

import type { Meta, StoryObj } from "@storybook/react-vite";
import { fn } from "storybook/test";
import { SubmitButton } from "./SubmitButton";

const meta = {
  title: "Forms/SubmitButton",
  component: SubmitButton,
  args: { label: "ارسال درخواست", busy: false, disabled: false, onClick: fn() },
  parameters: { layout: "centered" },
} satisfies Meta<typeof SubmitButton>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Ready: Story = {};
export const Busy: Story = { args: { busy: true } };
export const Disabled: Story = { args: { disabled: true } };

npm run storybook فرمان معمول اجرای محیط ساخته‌شده توسط CLI است. فایل‌ها را در پروژه‌ای بگذارید که الگوی stories در تنظیماتش همین پسوند را شامل می‌شود. برای تهیه خروجی قابل انتشار محیط مستند، script ساخت Storybook ایجادشده در package.json را استفاده کنید. معرفی این دستورها نتیجه اجرای آزمایش در این مقاله نیست و برای نصب خانواده دیگری باید مستند همان نسخه را خواند.

داستان Ready یک دکمه آماده عمل است. Busy متن وضعیت را دارد و کنترل غیرفعال است. Disabled یک علت محصولی برای غیرفعال بودن را نشان می‌دهد که در نمونه فقط یک prop آموزشی است؛ در رابط واقعی، اگر کاربر دلیل را نمی‌فهمد باید توضیحی نزدیک عمل ارائه شود. تغییر رنگ دکمه به تنهایی توضیح وضعیت نیست.

Component منفرد و جریان کامل دو محدوده‌اند

دکمه نمونه قراردادی درباره نمایش و فعال بودن دارد، اما نمی‌داند چه زمانی داده فرم معتبر است یا ارسال موفق شده. در صفحه واقعی، والد وضعیت درخواست را مدیریت می‌کند و به دکمه می‌دهد. اگر همه این منطق در خود دکمه پنهان شود، استفاده دوباره دشوارتر می‌شود. مرز component باید با وظیفه‌اش هماهنگ باشد.

برای نمایش جریان کامل، component بزرگ‌تری می‌تواند state محلی یا mock data داشته باشد، ولی محدوده آن را بنویسید. mock نباید وانمود کند اتصال واقعی به سرویس برقرار است. اگر یک پاسخ نمونه همواره موفق است، حالت خطا هنوز تعریف نشده است. مقاله Loading States به طراحی انتظار و پیام خطا به راه ادامه هنگام شکست مربوط است.

Visual و Interaction بررسی‌های متفاوت‌اند

Visual comparison تغییر ظاهر را دنبال می‌کند؛ interaction بررسی می‌کند پس از عمل، رفتار مورد انتظار رخ می‌دهد یا نه. اختلاف تصویر الزاماً bug نیست و شباهت تصویر هم سلامت رفتار را اثبات نمی‌کند. راهنمای بررسی‌ها در Storybook 9 این گردش کار را معرفی می‌کند. ابزار، integration و محیط اجرای هر بررسی را جدا انتخاب کنید.

برای نمونه دکمه، بررسی معنادار می‌تواند این باشد که در busy عمل دوباره آغاز نمی‌شود یا متن وضعیت درست است. مقایسه تصویری نیز می‌تواند تغییر ناخواسته چیدمان متن بلند را پیدا کند. بررسی‌ای که تنها وجود همان class نوشته‌شده را تأیید می‌کند، اطلاعات کمی درباره تجربه کاربر می‌دهد. هدف باید حفاظت از قرارداد باشد، نه زیاد کردن تعداد گزارش‌های سبز.

نتیجه مقایسه تصویر نیاز به داوری دارد. تغییر فونت محیط، animation یا داده متغیر می‌تواند اختلاف ایجاد کند. برای حالت مستند، این عوامل را قابل پیش‌بینی کنید. اگر هر اختلاف بدون بررسی تأیید شود، baseline معنای خود را از دست می‌دهد. مسئول تأیید تغییر باید بداند انتظار محصول چیست و کدام قسمت تصویر به آن مربوط است.

مستند را با خود component نگه دارید

Story جدا از کد اصلی نباید نسخه‌ای نمایشی با implementation دیگر باشد. اگر تیم فقط نمونه را اصلاح کند و component مصرف‌شده در محصول تغییر نکند، مستند اعتمادپذیر نیست. فایل نمونه باید همان export واقعی را import کند. در بازطراحی API هم Storyهای مرتبط را در همان تغییر مرور کنید تا مثال قدیمی راهنمای غلط ندهد.

برای component مشترک، نام propها و علت حالت‌ها را مستند کنید. واژه‌ای مثل compact باید رفتار مشخصی داشته باشد؛ آیا فاصله کم می‌شود یا اندازه متن هم تغییر می‌کند؟ اگر معنای prop میان componentها متفاوت است، مصرف‌کننده مجبور می‌شود کد را حدس بزند. یک مستند کوتاه دقیق از توضیح طولانی درباره «انعطاف بالا» مفیدتر است.

همه پروژه‌ها الزام یکسان برای Storybook ندارند. در محصول کوچک، هزینه نگهداری محیط باید با نیاز مرور و تعداد componentهای مشترک سنجیده شود. در تیمی که چند صفحه از component واحد استفاده می‌کنند، حالت‌های ثبت‌شده همکاری را روشن‌تر می‌کنند. انتخاب ابزار را به مسئله تیم وصل کنید و آن را شرط «جدی بودن» توسعه‌دهنده ندانید.

گام بعدی، انتخاب یک component پرمصرف و ثبت حالت‌های واقعی آن است. داده نمونه، وابستگی theme و رفتار کاربر را مشخص کنید و همان component محصول را در Story استفاده کنید. برای هماهنگی این تغییرها با انتشار، مقاله CI/CD فرانت‌اند ادامه مرتبطی است. ارزش محیط کارگاه از قراردادهای قابل استفاده می‌آید، نه از تعداد Storyهایی که فقط ظاهر حالت عادی را تکرار می‌کنند.

واکنش به این مقاله

اشتراک‌گذاری این مقاله:
دیدگاه‌ها 0
۰ / ۲۰۰۰

هنوز دیدگاهی ثبت نشده

اولین نفری باشید که نظر می‌دهد!