سیستم طراحی با Tailwind و shadcn/ui یعنی مالکیت کد، نه نصب پکیج
سیستم طراحی اگر فقط کتابخانه کامپوننت باشد، زود یا زندان میشود یا رها میشود. زندان وقتی است که هر انحراف از برند نیاز به جنگ با API کتابخانه دارد. رها شدن وقتی است که هر کس کارت خودش را میسازد و اسمش را سیستم میگذارد.
ترکیب Tailwind و shadcn/ui برای من جای وسط است. Tailwind مقیاس و توکن را میدهد. shadcn/ui الگوی کامپوننت را با Radix میآورد، ولی بهصورت کد داخل ریپو، نه وابستگی بسته که رفتارش را از راه دور عوض کند. این خوب است به شرطی که بدانی چه چیزی را داری مالک میشوی.
چرا کپی بهتر از جعبه سیاه است، تا یک جایی
کتابخانه کلاسیک را نصب میکنی و import میکنی. نسخه بعدی یا مشکل تو را حل میکند یا استایل را میشکند. shadcn/ui مسیر دیگری دارد: کد را به پروژه خودت میآوری. hover را عوض میکنی، variant اضافه میکنی، و منتظر merge غریبه نمیمانی.
این آزادی مسئولیت است. دیگر «باگ کتابخانه» بهتنهایی وجود ندارد. کد مال توست. اگر بیبرنامه هر دکمه را در همان فایل صفحه دست بزنی، شش کپی از Dialog داری که هیچکدام با هم یکی نیستند. مالکیت یعنی یک منبع. کپی اولیه شروع کار است، نه اجازه تکثیر.
Radix زیر این کامپوننتها رفتار دسترسپذیری را جدی گرفته: فوکوس، صفحهکلید، نقشها. این بخش را سبک ننویس. اگر Dialog را از نو با div میسازی چون «سادهتر است»، همان روزی که فوکوس از مودال بیرون میماند هزینه را پس میدهی. سفارشیسازی را روی ظاهر و ترکیب بگذار، نه روی دور انداختن رفتار پایه، مگر اینکه واقعاً آن رفتار را فهمیده باشی.
توکن قبل از کامپوننت
رنگ، شعاع، فاصله، سایه، و تایپ را در تم Tailwind و متغیرهای CSS بگذار. shadcn/ui معمولاً روی همین متغیرها سوار است. اگر متغیر `--primary` را در هر صفحه جور دیگری تعریف کنی، کامپوننتها ظاهر سیستم را دارند و برند را نه.
اسم توکن را از قصد محصول بگیر، نه از مقدار امروز. primary و destructive و muted، بهتر از blue و red زنده میمانند وقتی برند کمی عوض شود. مقدار آبی را یکجا عوض میکنی. اگر کلاس `bg-blue-600` در عمق کامپوننتهای کپیشده مانده باشد، باید شکارش کنی.
حالت روشن و تیره را روی همان متغیرها تعریف کن. کامپوننت نباید خودش رنگ خام ذخیره کند. اگر مجبور شد، استثناء را بنویس تا بعداً بدانیم چرا از سیستم خارج شده.
تایپ را هم محدود کن. اگر هر عنوان اندازه دلخواه دارد، مقیاس تایپ وجود ندارد. چهار یا پنج نقش متن برای محصول معمولی کافی است. بقیه استثناء صفحهاند و باید به چشم بیایند.
ساختار پوشه را مثل مرز دامنه بچین
سه لایه کافی است. توکن و استایل پایه. کامپوننت اولیه مثل دکمه، ورودی، دیالوگ، منو. کامپوننت ترکیبی مثل نوار فیلتر یا ردیف جدول که مال دامنه محصول است.
لایه سوم را داخل پوشه UI عمومی قاطی نکن. ردیف فاکتور، کامپوننت طراحی نیست؛ کامپوننت محصول است که از طراحی استفاده میکند. اگر این دو را یکی کنی، سیستم پر از قواعد کسبوکار میشود و در پروژه بعدی به درد نمیخورد. حتی اگر پروژه بعدی در کار نباشد، همین ریپو دو سال بعد شلوغ میشود.
TypeScript را از همان کامپوننت پایه جدی بگیر. variantها اگر رشته آزاد باشند، سیستم بهتدریج حالتهای بینام میگیرد. اتحاد نوع برای variant، ارزانترین سندی است که تیم واقعاً میخواند، چون کامپایلر مجبورش میکند.
نسخه و بهروزرسانی را مراسمی کن
چون کد را کپی کردهای، بهروزرسانی بالادست خودکار نیست. این را بپذیر. گاهبهگاه diff کامپوننت بالادست را ببین، مخصوصاً برای اصلاح دسترسپذیری و باگ فوکوس. اگر کامپوننت را آنقدر عوض کردهای که diff بیمعنی است، دیگر مصرفکننده آن الگو نیستی؛ مالک یک پیادهسازی سفارشی هستی. هر دو حالت قابل دفاع است اگر خودت بدانی کدامی.
قانون عملی: ظاهر برند را در توکن و لایه نازک دور کامپوننت عوض کن. منطق باز و بسته شدن، فوکوس، و ترکیب ARIA را تا جای ممکن دستنخورده نگه دار. جایی که دست میزنی، یک خط توضیح بگذار. شش ماه بعد هیچکس یادش نیست چرا `onCloseAutoFocus` عوض شده.
آیکون، انیمیشن، و جهت راستبهچپ را همان اول در یکی دو کامپوننت پررفتوآمد حل کن. محصول فارسی اگر فقط `dir` را روی بدنه بگذارد ولی منو و دیالوگ را با فرض چپبهراست کپی کند، سیستم روی زبان خودش میشکند. یک صفحه واقعی RTL را معیار بگیر، نه صفحه آزمایشی انگلیسی.
چه چیزی را وارد سیستم نکن
هر چیزی که یکبار در یک صفحه دیده شده. سیستم جای آزمایش بصری نیست. اول در صفحه محصول حلش کن. اگر الگوی دوم تکرار شد، آن وقت استخراج کن. استخراج زودهنگام، API خیالی میسازد.
نمودار، ویرایشگر متن، و جدول خیلی خاص دامنه را پشت ظاهر سیستم ببر، ولی پیادهسازیشان را داخل هسته UI قایم نکن. وابستگی سنگینشان باید مال همان ویژگی باشد تا باندل همه صفحهها را چاق نکند.
و مستند را جدا از کد نخشکان. اگر Storybook یا صفحه سند داخلی داری، مثال باید از همان کامپوننت ریپو بیاید. سند تصویری که با کد فرق دارد، کسی را ملزم نمیکند. برای تیم کوچک، یک مسیر `/dev/ui` داخل خود اپ اغلب کافی است و از زیرساخت جدا کمتر دروغ میگوید.
نقش برنامهنویس ارشد اینجا
کار من معمولاً این نیست که بیست کامپوننت دیگر اضافه کنم. این است که بگویم این یکی نباید ساخته شود، این variant تکراری است، و این رنگ خارج از توکن است. سیستم مقیاسپذیر یعنی نه گفتن به استثناء بینام.
اگر امروز فقط دکمه و ورودی و دیالوگ را یکدست کنی و توکن رنگ را واقعاً یک منبع باشد، از بیشتر «سیستم طراحی»هایی که با اسلاید شروع میشوند جلوتری. بقیه را وقتی درد تکرار را دیدی اضافه کن.
پرسشهای کوتاه
حتماً باید shadcn/ui باشد؟ نه. الگو مهم است: کد در ریپو، رفتار قابل دسترس، استایل از توکن. اگر تیم کتابخانه دیگری را همینطور مالک شود، همان کار را میکند.
هر صفحه حق دارد کامپوننت را کمی عوض کند؟ برای چیدمان بله. برای رفتار کنترل پایه نه. وگرنه سیستم فقط نقطه شروع کپی است.
با طراح چطور همزبان شویم؟ روی توکن و نام variant، نه روی نام کلاس. اگر نامها در فیگما و کد یکی باشد، بحث حاشیه و شعاع کوتاه میشود.