Trumpai
- Kodėl sukūrėme dizaino sistemą. Kai esate trejetukas, vienu metu tvarkantis dešimtis klientų projektų, neatitikimai tampa brangiausiu jūsų problemu.
- Pradėti nuo mažų dalykų, pirmiausia žetonai. Kiekvienas dizaino sistemos mokymasis sako pradėti nuo žetonų, ir tam yra gera priežastis.
- Komponentų architektūra. Turėdami žetonus, kreipėmės į komponentus.
- Dokumentacija, kurią realiai naudoja. Dokumentacija, tai vieta, kur dauguma mažų komandų dizaino sistemų žūva.
- Vizualinio nuoseklumo testavimas. Funkciniai testai parodo, ar mygtukas suaktyvina onClick handlerį.
Kodėl sukūrėme dizaino sistemą
Kai esate trejetukas, vienu metu tvarkantis dešimtis klientų projektų, neatitikimai tampa brangiausiu jūsų problemu. Pastebėjome tą pačią tendenciją kartojasi mūsų svetainių kūrimo projektuose GRADAX: mygtukas viename puslapyje stilizuotas vienaip, kitame, kitaip, o dashboard’e, trečiaip. Kiekvienas nukrypimas kainavo laiko QA etape, įnešė vizualinių klaidų ir erodavo poliruotą pojūtį, kurio tikėjosi klientai. Reikėjo kažką keisti.
Sprendimą investuoti į dizaino sistemą lėmė ne ambicijos ar mados siekimas. Jį lėmė skausmas. Kiekvienam naujam projektui skirdavome maždaug 30 % laiko iš naujo kurdami komponentus, kurie jau egzistavo kažkur kitur mūsų kodo bazėje. Dizaino sistema leistų mums vieną kartą užfiksuoti savo sprendimus ir naudoti juos visur, paverčiant pasikartojantį darbą konkurenciniu pranašumu.
Bet literatūra apie dizaino sistemas dominuojama istorijų iš kompanijų, turinčių skirtas platformos komandas iš dvidešimt ar daugiau inžinierių. Mums reikėjo praktiško požiūrio, kurį trejetukas galėtų sukurti, išlaikyti ir realiai naudoti neužblokuodamas funkcionalumo darbo. Toliau pateikiame rėmą, prie kurio priėjome po mėnesių iteracijų.
Pradėti nuo mažų dalykų, pirmiausia žetonai
Kiekvienas dizaino sistemos mokymasis sako pradėti nuo žetonų, ir tam yra gera priežastis. Dizaino žetonai yra atomines vertes: spalvos, tarpai, tipografijos masteliai, kampų spinduliai, iš kurių viskas kita yra statoma. Jie yra bet kokios vientisos prekės ženklo tapatybės pamatas, užtikrinant vizualinį nuoseklumą visuose taškuose. Mes apibrėžėme juos kaip CSS custom properties viename faile, susietus su semantiniais pavadinimais kaip --color-primary, --color-muted-foreground ir --radius-lg. Tai reiškė, kad bet kuris komponentas, remiantis šiais žetonais, automatiškai prisitaikytų, kai keičiamos pagrindinės vertės.
Pagrindinė mintis mažai komandai yra žetonų rinkinį laikyti griežtai mažą. Pradėjome nuo mažiau nei keturiasdešimties žetonų, apimančių spalvas, tarpus, tipografiją ir šešėlius. Didelės organizacijos gali prireikti šimtų, bet mes pastebėjome, kad kompaktiškas rinkinis verčia prie nuoseklumo, o ne leidžia tūkstančius subtilių variacijų. Kai programuotojas ima tarpų vertę ir turi tik aštuonis pasirinkimus, jis natūraliai renkasi tinkamą.
Taip pat anksti nustatėme pavadinimų konvenciją: semantinę, o ne deskriptorių. Vietoj --blue-600 ar --spacing-16, mes naudojome --color-primary ir --space-md. Tai atskilo intenciją nuo implementacijos ir palengvino būsimus pertvarkymus. Kai klientas norėjo pereiti nuo mėlynos prie violetinės, mes pakeitėme šešias eilutes žetonų faile ir visa sistema atsinaujino.

Komponentų architektūra
Turėdami žetonus, kreipėmės į komponentus. Pasirinkome shadcn/ui kaip pagrindą, kuris suteikė gražiai pagamintas, prieinamas primitives, pastatytas ant Radix UI. Vietoj to, kad statytume viską nuo nulio, mes plėtėme šias primitives su savo žetonų sluoksniu ir projekto specifiniais variantais. Pavyzdžiui, Button paveldėjo shadcn prieinamumą ir klaviatūros valdymą, naudodamas mūsų žetonų spalvų paletę ir tarpus.
Mūsų komponentų architektūra seka griežtą hierarchiją. Apačioje sėdi UI primitives: mygtukai, input’ai, badge’ai, tooltips, kurie neturi verslo logikos ir priima stilius per props ir className merging per cn() utilitetą. Virš jų sėdi sudedamos komponentės: paieškos juostos, duomenų lentelių įrankių juostos, statistikos kortelės, kurios jungia kelias primitives į pakartotinai naudojamus modelius. Viršuje sėdi puslapio lygio sekcijos, kurios yra specifinės vienam vaizdui ir yra kolokuotos šalia puslapio, kuris jas naudoja.
Šis trijų lygių modelis išvengia dviejų dažniausių dizaino sistemos nesėkmių: komponentų, kurie yra per daug abstraktūs, kad būtų naudingi, ir komponentų, kurie yra per specifiniai, kad būtų pakartotinai naudojami. Kai programuotojui reikia sukurti naują funkciją, jis ją surenka iš vidurinio lygio. Kai vidurinis lygis neturi to, ko jam reikia, jis ją sudaro iš primitives ir, jei ji pasirodo pakartotinai naudojama, promocioja ją.
Dokumentacija, kurią realiai naudoja
Dokumentacija, tai vieta, kur dauguma mažų komandų dizaino sistemų žūva. Komanda sukuria gražius komponentus, bet niekada neužrašo, kaip jais naudotis, todėl nauji kūrėjai (arba patys autoriai po trijų mėnesių) iš naujo sugalvoja jau egzistuojančius sprendimus. Mes tai išsprendėme paverčiant dokumentaciją kūrybos šalutiniu produktu, o ne atskiru uždaviniu.
Kiekviename komponento faile įtrauktas JSDoc blokas, aprašantis jo paskirtį, props sąsają ir naudojimo pavyzdį. Taip pat palaime gyvą Storybook instanciją, kurioje kiekvienas komponentas atvaizduojamas izoliuotai su visomis savo variacijomis. Svarbiausia taisyklė: jokio pull request nepriimame be atitinkamo „story“. Atrodo griežtai, tačiau tam užtenka penkių minučių vienam komponentui, o tai sutaupo valandas ateities painiavos.
Taip vedame lengvą sprendimų registrą, paprastą markdown failą, kuriame fiksuojame, kodėl priėmėme konkrečius sprendimus. Kodėl pasirinkome 0.5rem kaip bazinį kampų spindulį? Kodėl pagrindinė spalva naudoja oklch, o ne hex? Šios pastabos yra nepakeičiamos grįžtant prie sprendimų po šešių mėnesių ir padeda integruoti laisvai samdomus specialistus ar rangovus, prisijungiančius laikinai.
Vizualinio nuoseklumo testavimas
Funkciniai testai parodo, ar mygtukas suaktyvina onClick handlerį. Vizualiniai regresijos testai parodo, ar jis vis dar atrodo teisingai. Dizaino sistemai antrasis yra ne mažiau svarbus nei pirmasis. Integruojame Playwright ekrano kopijų palyginimą į CI pipeline, kad kiekvienas pull request generuotų paveiktų komponentų vizualų skirtumą.
Sąranka buvo paprastesnė, nei tikėjomės. Kiekviena Storybook istorija veikia ir kaip vizualus testavimo atvejis. Mūsų CI užduotis paleidžia headless naršyklę, fiksuoja kiekvienos istorijos ekrano kopijas ir lygina jas su fiksuotomis bazinėmis reikšmėmis. Jei komponento išvaizda pasikeičia bent vienu pikseliu, PR pažymimas peržiūrai. Tai pagavo dešimtis subtilių regresijų, kurios būtų patekusios į produkciją nepastebėtos, pavyzdžiui, rėmelio spalvos pasikeitimą, kai kas nors atnaujino tokeną nesuvokdamas to poveikio grandinės gale.
Taip pat vykdome vizualinius testus tiek šviesioje, tiek tamsioje temose. Kadangi mūsų tokenai apibrėžia atskiras reikšmes kiekvienai temai, pokytis, kuris atrodo tinkamas šviesioje temoje, gali visiškai sugadinti tamsiąją. Automatizuotos abiejų temų ekrano kopijos pašalino visą kategoriją klaidų, kurios anksčiau pasiekdavo produkciją.
Sistemos mastelio didinimas
Po šešių mėnesių naudojimo dvylikoje klientų projektų mūsų dizaino sistema išaugo nuo keturiasdešimt tokenų ir dvylikos komponentų iki maždaug aštuoniasdešimt tokenų ir keturiasdešimt penkių komponentų. Klausimas nebebuvo apie tai, ar plėsti sistemą, o apie tai, kaip tai padaryti neprarasdami paprastumo, kuris suteikė sistemai vertės iš pradžių.
Įvedėme indėlių kontrolinį sąrašą, kurį turi įvykdyti kiekvienas naujas komponentas prieš prisijungdamas prie bibliotekos: jis turi naudoti tik esamus tokenus, turi būti prieinamas iš karto (accessible), turi turėti bent vieną Storybook istoriją ir veikti tiek šviesioje, tiek tamsioje temose. Komponentai, neatitinkantys bet kurio kriterijaus, lieka projekto specifiniame kode kol jie bus sustiprinti. Ši kontrolė išlaiko bendros bibliotekos patikimumą.
Taip pat pradėjome versijuoti sistemą naudodami semantic releases. Lūžančius pokyčius (breaking changes) tokene arba komponento prop'e atspindi major versijos numerio padidinimas, todėl projektai, priklausantys nuo senesnės versijos, netrukdomai neveikia netikėtai. Pradžioje tai atrodė per daug trijų žmonių komandai, tačiau tai atsilošė, kai pradedome dalintis sistema su laisvai samdomais bendradarbiais ir specializuotomis kūrimo komandomis, kurioms reikėjo stabilumo garantijų.
Išvados
Svarbiausia pamoka yra ta, kad dizaino sistemai nebūtina būti milžiniška, kad būtų vertinga. Mūsų sistema pagal įmonių standartus yra maža, tačiau ji sutaupo mums apie dešimt valandų projekte dėl sumažinto dubliavimo, mažesnio vizualinių klaidų skaičiaus ir greitesnio integracijos. Trijų žmonių komandai, apmokestinamai pagal projektą, šios valandos tiesiogiai virsta pelnu.
Antra pamoka, optimizuokite priėmimą, o ne pilnatvę. Dizaino sistema, kurios jūsų komanda nenaudoja, yra blogesnė už jokios sistemos nebuvimą, nes ji sukuria nuoseklumo iliuziją, kol kodų bazė tuo tarpu diverguoja. Kiekvienas mūsų sprendimas, nuo shadcn/ui pasirinkimo kaip pagrindo iki Storybook istorijų privalomumo, buvo nukreiptas į tai, kad sistema taptų lengviausiu keliu, o ne papildoma našta.
Galiausiai, traktuokite savo dizaino sistemą kaip produktą su savo maršrutu, net jei vieninteliai vartotojai yra jūsų pačių komanda. Prioritetu nustatykite tuos komponentus ir tokenus, kurie eliminuos daugiausia dubliavimo. Stebėkite, kurie komponentai naudojami dažniausiai, ir investuokite į jų kokybę. Dizaino sistema niekada nėra baigta, tačiau su teisingais prioritetais net maža komanda gali ją palaikyti taip, lyg jos svoris būtų daug didesnis. Jei svarstote sukurti dizaino sistemą savo produktui ir norite gairių, nuo ko pradėti, susisiekite su mumis, mes esame praėję šį procesą ir galime padėti išvengti dažniausių klaidų.



