Ukratko
- Zašto smo izgradili dizajnerski sustav. Kada ste tim od tri osobe koji istovremeno obrađuje desetine klijentskih projekata, nedosljednost postaje vaš najskuplji problem.
- Početak s malim koracima, prvo tokeni. Svaki tutorial o dizajnerskim sustavima govori da treba početi s tokenima, i to iz dobre razloge.
- Arhitektura komponenti. S postavljеним tokenima, okrenuli smo se komponentama.
- Dokumentacija koja se zapravo koristi. Dokumentacija je mjesto gdje većina dizajn sustava malih timova propada.
- Testiranje vizualne usklađenosti. Funkcionalni testovi govore vam ispaljuje li gumb svoj onClick handler.
Zašto smo izgradili dizajnerski sustav
Kada ste tim od tri osobe koji istovremeno obrađuje desetine klijentskih projekata, nedosljednost postaje vaš najskuplji problem. Primijetili smo isti obrazac koji se ponavljao kroz naše angažmane na razvoju web stranica u GRADAX-u: gumb stiliziran na jedan način na početnoj stranici, na drugi na stranici s cijenama i na treći unutar nadzorne ploče. Svako odstupanje nas koštalo je vremena u QA testiranju, uvodilo vizualne greške i erodiralo profinjeni dojam koji su naši klijenti očekivali. Nešto se moralo promijeniti.
Odluka o ulaganju u dizajn sustav nije bila vođena ambicijom ili praćenjem trendova. Bila je vođena boli. Trošili smo otprilike 30% svakog novog projekta na ponovno stvaranje komponenti koje su već postojale u nekom obliku drugdje u našoj bazi koda. Dizajn sustav bi nam omogućio da svoje odluke kodiramo jednom i ponovno ih koristimo svugdje, pretvarajući repetitivni rad u konkurentsku prednost.
No, literatura o dizajnerskim sustavima dominirana je pričama iz tvrtki s posvećenim platformskim timovima od dvadeset ili više inženjera. Trebao nam je praktičan pristup koji bi tim od tri osobe mogao izgraditi, održavati i stvarno koristiti bez zaustavljanja razvoja funkcionalnosti. Ono što slijedi je okvir na koji smo došli nakon mjeseci iteracija.
Početak s malim koracima, prvo tokeni
Svaki tutorial o dizajnerskim sustavima govori da treba početi s tokenima, i to iz dobre razloge. Dizajnerski tokeni su atomskie vrijednosti, boje, razmaci, tipografske ljestvice, radijusi rubova, od kojih je sve drugo izgrađeno. Oni su temelj svake koherentne brand identitete, osiguravajući vizualnu dosljednost na svakoj točki dodira. Definirali smo ih kao CSS custom properties u jednoj datoteci, mapirane na semantička imena poput --color-primary, --color-muted-foreground i --radius-lg. To je značilo da bi svaka komponenta koja referencira ove tokene automatski prilagodila kada bismo promijenili osnovne vrijednosti.
Ključna spoznaja za mali tim jest da se skup tokena mora držati nemilosrdno malim. Krenuli smo s manje od četrdeset tokena koji pokrivaju boje, razmake, tipografiju i sjene. Velike organizacije mogu trebati stotine, ali mi smo utvrdili da kompaktan skup nameće dosljednost umjesto da omogućuje tisuću suptilnih varijacija. Kada developer posegne za vrijednošću razmaka i ima samo osam opcija, prirodno će pogoditi onu pravu.
Rano smo uspostavili i konvenciju imenovanja, semantičku umjesto deskriptivnu. Umjesto --blue-600 ili --spacing-16, koristili smo --color-primary i --space-md. Ovo je razdvojilo namjeru od implementacije i učinilo buduće redesignove trivijalnim. Kada je klijent želio prijeći s plave na ljubičastu, promijenili smo šest linija u datoteci s tokenima i cijeli sustav se ažurirao.

Arhitektura komponenti
S postavljеним tokenima, okrenuli smo se komponentama. Usvojili smo shadcn/ui kao svoju osnovu, što nam je dalo predivno izrađene, pristupačne primitive izgrađene na Radix UI. Umjesto da gradimo sve od nule, proširili smo ove primitive slojem tokena i specifičnim varijantama projekta. Gumb, na primjer, nasljeđuje shadcnovu pristupačnost i rukovanje tipkovnicom, dok koristi našu paletu boja vođenu tokenima i razmake.
Naša arhitektura komponenti slijedi strogu hijerarhiju. Na dnu sjede UI primitive, gumbi, inputi, badgeovi, tooltipovi, koji nemaju posla s poslovnom logikom i prihvaćaju stiliziranje putem propsa i spajanja className putem cn() utility funkcije. Iznad njih sjede komponirane komponente, trake za pretraživanje, alatne trake tablica s podacima, kartice sa statistikom, koje kombiniraju više primitiva u reupotrebljive obrasce. Na vrhu sjede sekcije na razini stranice koje su specifične za jedan prikaz i nalaze se zajedno sa stranicom koja ih koristi.
Ovaj model s tri razine sprječava dva najčešća neuspjehа dizajnerskih sustava: komponente koje su previše apstraktne da bi bile korisne i komponente koje su previše specifične da bi bile reupotrebljive. Kada developer treba izgraditi novu funkcionalnost, sastavlja je iz srednje razine. Kada srednja razina nema ono što mu treba, komponira ga iz primitiva i, ako se pokaže reupotrebljivim, promovira ga.
Dokumentacija koja se zapravo koristi
Dokumentacija je mjesto gdje većina dizajn sustava malih timova propada. Tim izradi prekrasne komponente, ali nikad ne zapiše kako se koriste, pa novi suradnici (ili izvorni autori nakon tri mjeseca) ponovno izmišljaju obrasce koji već postoje. Riješili smo to tako da dokumentaciju učinimo nusproizvodom razvoja, a ne zasebnim zadatkom.
Svaka datoteka komponente uključuje JSDoc blok koji opisuje njezinu svrhu, sučelje svojstava (props) i primjer korištenja. Također održavamo živu instancu Storybooka u kojoj se svaka komponenta prikazuje izolirano sa svojim varijantama. Ključno pravilo je da se pull request ne spaja bez odgovarajuće priče (story). Ovo zvuči strogo, ali traje manje od pet minuta po komponenti i štedi sate buduće zbunjenosti.
Također vodimo lagani zapisnik odluka, jednostavnu markdown datoteku koja bilježi zašto smo donijeli određene izbore. Zašto smo odabrali 0.5rem kao osnovni polumjer? Zašto naša primarna boja koristi oklch umjesto hexa? Ove bilješke neprocjenjive su prilikom ponovnog pregleda odluka nakon šest mjeseci i pomažu u onboarding-u freelancerima ili ugovornim suradnicima koji se privremeno pridružuju timu.
Testiranje vizualne usklađenosti
Funkcionalni testovi govore vam ispaljuje li gumb svoj onClick handler. Vizualni regresijski testovi govore vam izgleda li i dalje ispravno. Za dizajn sustav ovo drugo jednako je važno kao i prvo. Integrirali smo usporedbu snimaka ekrana Playwrighta u naš CI pipeline kako bi svaki pull request generirao vizualnu razliku (diff) zahvaćenih komponenti.
Postavka je bila jednostavnija nego što smo očekivali. Svaka Storybook priča istovremeno služi i kao vizualni testni slučaj. Naša CI zadaća pokreće headless preglednik, snima slike svake priče i uspoređuje ih s pohranjenim baznim vrijednostima. Ako se izgled komponente promijeni, čak i za jedan piksel, PR se označava na pregled. Ovo je uhvatilo desetine suptilnih regresija koje bi bile otpremljene nezapaženo, poput promjene boje obruba jer je netko ažurirao token ne shvaćajući njegov utjecaj na niz.
Također pokrećemo vizualne testove i u svijetlom i u tamnom načinu rada. Budući da naši tokeni definiraju odvojene vrijednosti za svaki način, promjena koja izgleda dobro u svijetlom načinu može potpuno pokvariti tamni način. Automatske snimke ekrana u oba načina eliminirale su cijelu kategoriju bugova koji su ranije stizali do produkcije.
Skaliranje sustava
Nakon šest mjeseci korištenja na dvanaest klijentskih projekata, naš dizajn sustav porastao je s četrdeset tokena i dvanaest komponenti na otprilike osamdeset tokena i četrdeset pet komponenti. Pitanje više nije bilo hoćemo li skalirati sustav, već kako to učiniti a da ne izgubimo jednostavnost koja ga je prvotno učinila vrijednim.
Uveli smo popis provjera za doprinos koji svaka nova komponenta mora proći prije ulaska u biblioteku: mora koristiti samo postojeće tokene, mora biti pristupačna „out of the box“, mora uključivati barem jednu Storybook priču i mora raditi u svijetlom i tamnom načinu rada. Komponente koje ne ispune nijedan kriterij ostaju u kodu specifičnom za projekt dok se ne učvrste. Ovaj nadzor održava povjerenje u zajedničku biblioteku.
Započeli smo i verzioniranje sustava pomoću semantičkih izdanja. Lomljive promjene na tokenima ili propovima komponenti očituju se kao veći skokovi verzija, tako da projekti zaključani na stariju verziju ne doživljavaju neočekivane kvarove. Na početku je to bilo pretjerano za tim od tri osobe, ali isplatilo se čim smo počeli dijeliti sustav s freelance suradnicima i namjenskim razvojnim timovima kojima su bila potrebna jamstva stabilnosti.
Pouke iz iskustva
Najvažnija pouka jest da dizajnerski sustav ne mora biti ogroman da bi bio vrijedan. Naš sustav je malen u odnosu na enterprise standarde, ali štedi nam procijenjenih deset sati po projektu smanjenjem dupliciranja, manjim vizualnim greškama i bržim onboardanjem. Za tim od tri osobe koji naplaćuje po projektu, ti sati izravno se pretvaraju u profitabilnost.
Druga pouka jest optimizirati za usvajanje, a ne za potpunost. Dizajnerski sustav kojim vaš tim ne koristi gori je od nikakvog dizajnerskog sustava jer stvara iluziju konzistentnosti dok se baza koda razilazi ispod površine. Svaka odluka koju smo donijeli, od izbora shadcn/ui kao temelja do obaveznog korištenja Storybook priča, imala je za cilj učiniti sustav najmanje otpornim putem, a ne dodatnim teretom.
Konačno, tretirajte svoj dizajnerski sustav kao proizvod sa vlastitom roadmapom, čak i ako su jedini korisnici vaši interni timovi. Prioritet dajte komponentama i tokenima koji će eliminirati najveće dupliciranje. Pratite koje su komponente najčešće korištene i ulažite u njihovu kvalitetu. Dizajnerski sustav nikada nije završen, ali s pravim prioritetima, čak i mali tim može održavati jedan koji daje rezultate znatno iznad svoje težine. Ako razmišljate o izradi dizajnerskog sustava za svoj produkt i želite smjernice gdje započeti, kontaktirajte naš tim, prošli smo kroz taj proces i možemo vam pomoći izbjeći najčešće zamke.



