Накратко
- Защо изградихме дизайн система. Когато сте екип от трима, който се занимава с десетки клиентски проекти едновременно, непоследователността се превръща в най-скъпия Ви проблем. Забелязахме, че същият модел се повтаря в нашите ангажименти за уеб дизайн в GRADAX: бутон, стилизиран по един начин на началната страница, по друг на страницата с цени и по трети в таблото за управление. Всяко отклонение ни струваше време в QA, въвеждаше визуални бъгове и подкопаваше излъсканото усещане, което клиентите ни очакваха. Нещо трябваше да се промени.
- Започваме малко, първо токените. Всяко ръководство за дизайн системи Ви казва да започнете с токени и то с основание. Дизайн токените са атомните стойности, цветове, отстояния, типографски скали, радиуси на рамки, от които се изгражда всичко останало. Те са основата на всяка сплотена бранд идентичност, осигурявайки визуална последователност във всяка точка на допир. Дефинирахме нашите като CSS custom properties в един файл, съпоставени на семантични имена като --color-primary, --color-muted-foreground и --radius-lg. Това означаваше, че всеки компонент, който реферира тези токени, автоматично ще се адаптира, когато променим основните стойности.
- Архитектура на компонентите. След като токените бяха налице, се обърнахме към компонентите. Възприехме shadcn/ui като наша основа, което ни даде красиво изработени, достъпни примитиви, изградени върху Radix UI. Вместо да изграждаме всичко от нулата, разширихме тези примитиви с нашия токен слой и специфични за проекта варианти. Един Button например наследяваше достъпността и обработката на клавиатурата на shadcn, като използваше нашата токен-базирана цветова палитра и отстояния.
- Документация, която наистина се използва. Документацията е мястото, където повечето дизайн системи на малки екипи загиват. Екипът създава красиви компоненти, но никога не записва как се използват, така че новите участници (или самите автори три месеца по-късно) преоткриват вече съществуващи модели. Решихме това, като превърнахме документацията в страничен продукт от разработката, а не в отделна задача.
- Тестване на визуалната консистентност. Функционалните тестове показват дали бутонът задейства своя onClick handler. Тестовете за визуална регресия показват дали все още изглежда правилно. За една дизайн система второто е също толкова важно, колкото първото. Интегрирахме сравнения на екранни снимки с Playwright в нашия CI pipeline, така че всеки pull request генерира визуален diff на засегнатите компоненти.
Защо изградихме дизайн система
Когато сте екип от трима, който се занимава с десетки клиентски проекти едновременно, непоследователността се превръща в най-скъпия Ви проблем. Забелязахме, че същият модел се повтаря в нашите ангажименти за уеб дизайн в GRADAX: бутон, стилизиран по един начин на началната страница, по друг на страницата с цени и по трети в таблото за управление. Всяко отклонение ни струваше време в QA, въвеждаше визуални бъгове и подкопаваше излъсканото усещане, което клиентите ни очакваха. Нещо трябваше да се промени.
Решението да инвестираме в дизайн система не беше продиктувано от амбиция или следване на тенденции. Беше продиктувано от болка. Харчехме приблизително 30% от всеки нов проект за пресъздаване на компоненти, които вече съществуваха в някаква форма другаде в кодовата ни база. Дизайн системата щеше да ни позволи да кодифицираме решенията си веднъж и да ги използваме навсякъде, превръщайки повтарящата се работа в конкурентно предимство.
Но литературата за дизайн системи е доминирана от истории на компании с посветени платформени екипи от двадесет или повече инженери. Нуждаехме се от прагматичен подход, който екип от трима може да изгради, поддържа и реално да използва, без да спира работата по функции. Това, което следва, е рамката, до която стигнахме след месеци итерации.
Започваме малко, първо токените
Всяко ръководство за дизайн системи Ви казва да започнете с токени и то с основание. Дизайн токените са атомните стойности, цветове, отстояния, типографски скали, радиуси на рамки, от които се изгражда всичко останало. Те са основата на всяка сплотена бранд идентичност, осигурявайки визуална последователност във всяка точка на допир. Дефинирахме нашите като CSS custom properties в един файл, съпоставени на семантични имена като --color-primary, --color-muted-foreground и --radius-lg. Това означаваше, че всеки компонент, който реферира тези токени, автоматично ще се адаптира, когато променим основните стойности.
Ключовият извод за малък екип е да поддържате набора от токени безпощадно малък. Започнахме с по-малко от четиридесет токена, обхващащи цвят, отстояние, типография и сенки. Големите организации може да се нуждаят от стотици, но открихме, че компактният набор налага последователност, вместо да позволява хиляда фини вариации. Когато разработчик посегне към стойност за отстояние и има само осем опции, той естествено избира правилната.
Също така установихме конвенция за именуване рано, семантична пред описателна. Вместо --blue-600 или --spacing-16, използвахме --color-primary и --space-md. Това отдели намерението от реализацията и направи бъдещите редизайни тривиални. Когато клиент поискаше да премине от синьо към виолетово, променихме шест реда в токен файла и цялата система се обнови.

Архитектура на компонентите
След като токените бяха налице, се обърнахме към компонентите. Възприехме shadcn/ui като наша основа, което ни даде красиво изработени, достъпни примитиви, изградени върху Radix UI. Вместо да изграждаме всичко от нулата, разширихме тези примитиви с нашия токен слой и специфични за проекта варианти. Един Button например наследяваше достъпността и обработката на клавиатурата на shadcn, като използваше нашата токен-базирана цветова палитра и отстояния.
Архитектурата на компонентите ни следва строга йерархия. Най-отдолу са UI примитивите, бутони, полета за въвеждане, баджове, подсказки, които нямат бизнес логика и приемат стилове чрез props и сливане на className чрез утилитата cn(). Над тях са композираните компоненти, ленти за търсене, ленти с инструменти за таблици с данни, карти със статистики, които комбинират множество примитиви в преизползваеми модели. Най-отгоре са секции на ниво страница, които са специфични за един изглед и са разположени до страницата, която ги използва.
Този тристепенен модел предотвратява двата най-чести провала на дизайн системите: компоненти, които са твърде абстрактни, за да бъдат полезни, и компоненти, които са твърде специфични, за да бъдат преизползваеми. Когато разработчик трябва да изгради нова функция, той я сглобява от средното ниво. Когато средното ниво няма това, от което се нуждае, той я композира от примитиви и, ако се окаже преизползваема, я повишава.
Документация, която наистина се използва
Документацията е мястото, където повечето дизайн системи на малки екипи загиват. Екипът създава красиви компоненти, но никога не записва как се използват, така че новите участници (или самите автори три месеца по-късно) преоткриват вече съществуващи модели. Решихме това, като превърнахме документацията в страничен продукт от разработката, а не в отделна задача.
Всеки файл на компонент включва JSDoc блок, описващ предназначението му, интерфейса на props и пример за употреба. Поддържаме и жива инстанция на Storybook, където всеки компонент се рендира изолирано с вариантите си. Критичното правило е, че нито един pull request не се слива без съответната story. Това звучи строго, но отнема по-малко от пет минути на компонент и спестява часове бъдещо объркване.
Поддържаме и лек дневник на решенията, прост markdown файл, който записва защо сме взели определени решения. Защо избрахме 0.5rem като базов радиус? Защо основният ни цвят използва oklch вместо hex? Тези бележки са безценни, когато преразглеждаме решения шест месеца по-късно, и помагат при включването на freelancers или contractors, които се присъединяват временно.
Тестване на визуалната консистентност
Функционалните тестове показват дали бутонът задейства своя onClick handler. Тестовете за визуална регресия показват дали все още изглежда правилно. За една дизайн система второто е също толкова важно, колкото първото. Интегрирахме сравнения на екранни снимки с Playwright в нашия CI pipeline, така че всеки pull request генерира визуален diff на засегнатите компоненти.
Настройката се оказа по-проста, отколкото очаквахме. Всяка Storybook story служи едновременно и като визуален тестов случай. Нашата CI задача стартира headless браузър, прави екранни снимки на всяка story и ги сравнява с ангажирани базови версии. Ако външният вид на компонент се промени, дори с един пиксел, PR се маркира за преглед. Това улови десетки фини регресии, които иначе щяха да стигнат до продукция незабелязано, като например промяна на цвят на рамка, защото някой е обновил token, без да осъзнава последствията надолу по веригата.
Също така пускаме визуални тестове както в светъл, така и в тъмен режим. Тъй като нашите tokens дефинират отделни стойности за всеки режим, промяна, която изглежда добре в светъл режим, може напълно да счупи тъмния. Автоматизираните екранни снимки в двата режима елиминираха цяла категория бъгове, които преди стигаха до продукция.
Мащабиране на системата
След шест месеца употреба в дузина клиентски проекти нашата дизайн система нарасна от четиридесет tokens и дванадесет компонента до приблизително осемдесет tokens и четиридесет и пет компонента. Въпросът вече не беше дали да мащабираме, а как да мащабираме, без да губим простотата, която правеше системата ценна на първо място.
Въведохме контролен списък за принос, който всеки нов компонент трябва да премине, преди да се присъедини към библиотеката: трябва да използва само съществуващи tokens, трябва да бъде достъпен веднага, трябва да включва поне една Storybook story и трябва да работи както в светъл, така и в тъмен режим. Компонентите, които не отговарят на който и да е критерий, остават в кода на конкретния проект, докато не бъдат укрепени. Този контрол поддържа споделената библиотека надеждна.
Също така започнахме да версионираме системата чрез semantic releases. Промените, които нарушават съвместимостта на token или prop на компонент, се отразяват като мажор версии (major version bumps), така че проектите, фиксирани към по-стара версия, не се чупят неочаквано. Първоначално това беше прекалено за екип от трима, но се отплати, когато започнахме да споделяме системата с freelance сътрудници и екипи за разработка по поръчка, които се нуждаеха от гаранции за стабилност.
Извлечени уроци
Най-важният урок е, че една дизайн система не трябва да бъде огромна, за да бъде ценна. Нашата система е малка по корпоративни стандарти, но ни спестява приблизително десет часа на проект чрез намалено дублиране, по-малко визуални бъгове и по-бързо включване. За екип от трима, който фактурира на проект, тези часове се превръщат директно в печалба.
Вторият урок е да оптимизирате за приемане, а не за пълнота. Дизайн система, която екипът ви не използва, е по-лоша от липсата на дизайн система, защото създава илюзия за консистентност, докато кодът под нея се разминава. Всяко решение, което взехме, от избора на shadcn/ui като основа до задължителните Storybook stories, беше насочено към това системата да бъде пътят на най-малко съпротивление, а не допълнително бреме.
Накрая, третирайте дизайн системата си като продукт със собствена пътна карта, дори ако единствените потребители са собственият ви екип. Давайте приоритет на компонентите и токените, които ще елиминират най-много дублиране. Проследявайте кои компоненти се използват най-често и инвестирайте в качеството им. Дизайн системата никога не е завършена, но с правилните приоритети дори малък екип може да поддържа такава, която се представя далеч над възможностите си. Ако обмисляте да изградите дизайн система за вашия продукт и искате насоки откъде да започнете, свържете се с нашия екип, ние сме минали през процеса и можем да ви помогнем да избегнете най-честите капани.



