رفتن به محتوای اصلی
← همه‌ی تصمیم‌ها

تم یک کانفیگ کامپایل‌شده است، نه یک رنگ

accepted

زمینه

نسخه‌ی اول این پلی‌گراند یک کد رنگ می‌گرفت، یک رمپ رنگ می‌ساخت و پوسته‌ی فروشگاه را عوض می‌کرد. از نظر فنی سخت‌ترین چیز روی صفحه بود — رمپ OKLCH با فاصله‌ی ادراکی یکنواخت، gamut mapping، اصلاح کنتراست بر اساس WCAG — و در نگاه بیننده یک کالر پیکر بود.

این برداشت درست بود و ارزش دارد دقیق بگویم چرا. یک ورودی، یک جنس خروجی. بیننده رنگ را می‌بیند که عوض می‌شود و منطقاً نتیجه می‌گیرد این سیستم رنگ عوض می‌کند. هیچ‌چیز در آن ادعای اصلی من را نشان نمی‌دهد: اینکه یک فریم‌ورک می‌تواند یک فروشگاه دیگر بسازد، نه یک فروشگاه رنگ‌عوض‌شده.

فروشگاه را تراکمش تعریف می‌کند، ریتمش، زبان فرم‌هایش، سلسله‌مراتب تایپوگرافی‌اش، و از همه مهم‌تر ساختارش. رنگ آخرین چیز در این فهرست است.

گزینه‌های بررسی‌شده

کنترل رنگ بیشتر. رنگ دوم، جفت‌های اکسنت، استاپ‌های گرادیان. این همان تله است — تعداد ورودی‌ها را زیاد می‌کند بدون اینکه جنس خروجی عوض شود.

تم‌ساز بصری با ورودی عددی آزاد. اسلایدر برای رادیوس، فاصله، اندازه‌ی فونت. رساتر است، اما کانفیگی که از عدد دلخواه ساخته شده نه ولیدیت می‌شود، نه وقتی اسکیما عوض شد می‌شود مایگریتش کرد، و نه کسی که بعداً تحویلش می‌گیرد می‌تواند درباره‌اش استدلال کند.

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

تصمیم

ورودی یک فایل است:

{
  "seed": "#e0541f", "scheme": "dark",
  "radius": "soft", "density": "comfortable", "elevation": "bordered",
  "typeScale": "default",
  "columns": 4, "imageRatio": "4/3", "cardStyle": "stacked"
}

compileTheme(config) نقش‌های رنگی، فاصله‌گذاری مشتق‌شده از یک گام تراکم، یک مقیاس تایپوگرافی مدولار، استراتژی ارتفاع و structure را برمی‌گرداند — و فروشگاه روی همین آخری برنچ می‌زند. cardStyle: 'stacked' | 'overlay' | 'horizontal' سه کامپوننت واقعاً متفاوت تولید می‌کند: ترتیب DOM متفاوت، محور چیدمان متفاوت، نسبت متفاوت میان تصویر و متن. مرز میان «تم‌گذاری» و «تولید» دقیقاً همین‌جاست.

هر فیلد یک یونیون بسته است، نه یک مقدار آزاد. سرسختانه‌ترین دفاعم از همین تصمیم است. یک واریانت به CardStyle اضافه کنید و هر مصرف‌کننده‌ای تا وقتی هندلش نکند کامپایل نمی‌شود. تم‌سیستمی که ورودی‌هایش عدد دلخواه‌اند چنین خاصیتی ندارد.

پلی‌گراند، کانفیگ را به‌شکل JSON قابل ویرایش کنار کنترل‌ها می‌گذارد و هر دو یک آبجکت واحد را می‌رانند. این عمدی است: تم یک مشتری چیزی است که کامیت می‌شود و در پول‌ریکوئست ریویو می‌شود، نه حالتی که کسی با چند کلیک به آن رسیده.

هزینه‌هایی که پذیرفتم

  • یونیون بسته دست را می‌بندد. مشتری‌ای که رادیوس ۱۷ پیکسل بخواهد نمی‌تواند داشته باشد. برای سیستمی که قرار است فروشگاه‌های متعدد و منسجم بسازد — نه یک فروشگاه دقیقاً سفارشی — این معامله را درست می‌دانم، اما محدودیت واقعی است و بالاخره کسی را اذیت می‌کند.
  • نُه محور بیشتر از آن است که بیننده حوصله کند. چهار پریست با شخصیت کامل گذاشته‌ام چون ادعای جالب این نیست که «نُه چیز قابل تنظیم است»، بلکه این است که «نُه چیز منسجم با هم حرکت می‌کنند» — و این با دو کلیک منتقل می‌شود، نه با نُه تا.
  • واریانت ساختاری سطح تست را چند برابر می‌کند. سه چیدمان کارت ضرب در چهار پریست یعنی دوازده ترکیب که همه باید کار کنند، و فقط یک گیت این را قابل مدیریت نگه می‌دارد.

نتیجه

چهار پریست، از یک موتور، چهار فروشگاهِ به‌طور قابل اندازه‌گیری متفاوت می‌سازند — از ۱ تا ۴ ستون، رادیوس ۰ تا ۲۸ پیکسل، ارتفاع کارت ۱۱۶ تا ۳۶۰ پیکسل، از تخت تا برجسته، در روشن و تیره.

تضمین دسترس‌پذیری هم از این گسترش جان سالم به در برد: ۱۴۴ جفت نقش رنگی در همه‌ی پریست‌ها و هر دو حالت، زمان بیلد بررسی می‌شوند و هرجا رد شوند خودکار اصلاح می‌شوند.

چه چیزی را عوض می‌کردم

دو چیز، و هر دو را با نگاه‌کردن به صفحه‌ی در حال اجرا پیدا کردم، نه با خواندن کد.

--color-surface را وادار کرده بودم به نسبت ۳:۱ با زمینه‌ی صفحه اصلاح شود. این غلط است — یک سطح برجسته پس‌زمینه است، نه کامپوننت رابط کاربری، پس معیار ۱.۴.۱۱ اصلاً شاملش نمی‌شود. همین اجبار، کارتی با رنگ #373937 را تا #6c6e6b بالا می‌کشید و همه‌ی کاشی‌های محصول خاکستریِ وسط می‌شدند. چیزی که باید در لبه‌ی کارت قابل تشخیص باشد بوردر آن است، که بررسی هم می‌شود. یک حالت سوم برای نقش‌ها اضافه کردم: گزارش می‌شود، هرگز اصلاح نمی‌شود. این حالت را از همان اول طراحی می‌کردم، نه اینکه روی صفحه کشفش کنم.

اولین کارت overlay من دکمه‌ی افزودن نداشت چون بدون آن ترکیب‌بندی تمیزتری داشت. یک واریانت چیدمان اجازه دارد ظاهر یک کنش را عوض کند؛ اجازه ندارد حذفش کند. این قاعده حالا در کامنتی کنار همان کدی نشسته که نزدیک بود آن را بشکند، و گیت تعداد کنش‌های اصلی هر کارت را در همه‌ی واریانت‌ها می‌شمارد.