Naming
Design system-ul și codul vorbesc două limbaje diferite. Ambele sunt reale, ambele rămân tokenizate — dar de la 26 august 2026 limbajul canonic e cel de cod. Pagina asta e dicționarul, și e generată din tokens.semantics.json, nu scrisă de mână.
Două limbaje
Limbajul de design — nume de culori
--c-bej-1, --c-fog, --c-pink-tint. Astea sunt numele pe care le-a dat stakeholder-ul când a proiectat sistemul, și sunt numele corecte în camera în care se ia decizia: „tonalul e bej-1" e o propoziție despre culoare.
Limbajul de cod — nume de roluri
--muted, --muted-foreground, --accent. Convenția shadcn. Un rol supraviețuiește unei schimbări de valoare; un nume de culoare nu. --c-bej-1 devine o minciună în ziua în care suprafața tonală nu mai e bej.
Al doilea motiv, mai practic: o valoare poate purta două roluri. --c-white e și cardul și popover-ul; --c-bej-1 e și suprafața tonală și fill-ul secundar. În limbajul de culori sunt un token folosit în două locuri, deci nu poți schimba unul fără celălalt. În limbajul de roluri sunt două tokene care momentan au aceeași valoare.
Ce s-a decis
Dicționarul · tokens.semantics.json → role_name
Suprafețe și text
| Limbajul de design | Limbajul de cod · canonic | Rolul |
|---|---|---|
--c-bej-0 | --background | suprafață pagină |
--c-bej-05 | --muted-subtle | hover de rând / listă — treapta dintre bej-0 și bej-1 |
--c-bej-1 | --muted | suprafață tonală / control neutru |
--c-fog | --muted-foreground | text secundar; focus ring |
--c-ink | --foreground | text primar pe fundal deschis |
--c-mist | --placeholder | text terțiar / sufix |
--c-white | --card | suprafață de bază |
Brand
| Limbajul de design | Limbajul de cod · canonic | Rolul |
|---|---|---|
--c-accent | --primary | brand — stări interactive și acțiune principală |
--c-accent-deep | --primary-hover | brand hover (alias) |
--c-accent-tint | --accent | brand tint (alias) |
--c-accent-ultra | --accent-subtle | brand wash (alias) |
Linii și borduri
| Limbajul de design | Limbajul de cod · canonic | Rolul |
|---|---|---|
--c-input-border | --input | border input și controale mici |
--c-input-border-hover | --input-hover | border input/select/controale mici pe hover — două trepte peste --c-input-border |
--c-input-border-tonal | --input-tonal | border input/select pe varianta .tonal — treapta minimă peste 3:1, calibrată pe gazdă albă sau bej-0: fundalul bej-0 nu separă câmpul, deci conturul duce singur limita controlului |
--c-rule | --separator | separator |
--c-rule-card | --border | border container |
--c-rule-hover | --separator-hover | separator pe hover — o treaptă peste --c-rule |
--c-rule-soft | --separator-subtle | separator discret |
Acțiune distructivă
| Limbajul de design | Limbajul de cod · canonic | Rolul |
|---|---|---|
--c-danger | --destructive | destructive control fill |
Familii de status
| Limbajul de design | Limbajul de cod · canonic | Rolul |
|---|---|---|
--c-ai | --ai | procesat / generat de AI — fill, stroke și text |
--c-ai-bg | --ai-subtle | fundal AI |
--c-ai-grad | --ai-gradient | gradient AI |
--c-error | --error | mesagerie de eroare — fill / stroke |
--c-error-bg | --error-subtle | fundal de mesaj de eroare |
--c-error-text | --error-subtle-foreground | text de eroare — singurul token de text al familiei |
--c-read | --read | status "citit / văzut" — fill |
--c-read-bg | --read-subtle | fundal status "citit" |
--c-read-text | --read-subtle-foreground | text status "citit" pe tint |
--c-success | --success | status pozitiv — fill / stroke |
--c-success-bg | --success-subtle | fundal status pozitiv |
--c-success-text | --success-subtle-foreground | text status pozitiv — singurul token de text al familiei |
--c-warn | --warning | status de atenție — fill / stroke |
--c-warn-bg | --warning-subtle | fundal status de atenție |
--c-warn-text | --warning-subtle-foreground | text status de atenție — singurul token de text al familiei |
Overlay
| Limbajul de design | Limbajul de cod · canonic | Rolul |
|---|---|---|
--c-backdrop | --overlay | scrim canonic — dim în spatele oricărui overlay de tip modal |
--scrim-blur | --overlay-blur | scrim canonic — blur în spatele oricărui overlay de tip modal, pereche cu --c-backdrop |
Altele
| Limbajul de design | Limbajul de cod · canonic | Rolul |
|---|---|---|
--layout-max | --layout-max-width | lățimea maximă a layout-ului funcțional pe desktop |
Fără nume de rol, deliberat
Tokenele astea rămân doar în limbajul de design, iar motivul e declarat în tokens.semantics.json. Lista nu e o restanță: e o decizie per token, și un token nou nu poate intra în sistem fără una.
| Token | De ce nu are rol |
|---|---|
--c-dark | Alias deprecat al fill-ului destructiv; pastrat doar pentru paginile inghetate din doc-originale. Rolul e --destructive, pe --c-danger. |
--c-dark-mid | Stop intermediar intr-un gradient decorativ (avatar). Nu e un rol semantic — nimic nu il alege pentru ce inseamna. |
--c-pdf-hl | Highlight de selectie in PDF viewer. Suprafata unica a unei singure componente; un nume de rol ar sugera reutilizare. |
--c-pink | Valoare de paletă, nu rol. --primary punteaza pe --c-accent, care aliaseaza acest token; brandul isi pastreaza numele ca sa rămână evident ce culoare e. |
--c-pink-deep | Valoare de paletă — rolul e --primary-hover, purtat de --c-accent-deep. |
--c-pink-tint | Valoare de paletă — rolul e --accent, purtat de --c-accent-tint. |
--c-pink-ultra | Valoare de paletă — rolul e --accent-subtle, purtat de --c-accent-ultra. |
--c-rule-soft-solid | Acelasi caz ca --c-rule-solid, pentru --c-rule-soft. Rolul e --separator-subtle. |
--c-rule-solid | Fallback opac pentru --c-rule, folosit unde alpha nu compune corect (peste imagini/gradient). Acelasi rol, mecanism diferit — rolul e --separator. |
--c-selection | Nu are corespondent în limbajul aplicației, și nu dintr-o scăpare: shadcn/ui nu are un token de selecție. Controalele lui poartă utilitarele `selection:bg-primary` / `selection:text-primary-foreground`, adică refolosesc tokenul de BRAND pentru un gest care nu e al aplicației — exact defectul pentru care există tokenul ăsta. Deci nu există un nume de rol pe care să-l revendice; ce trebuie făcut la adopție e opusul, se ȘTERG clasele alea de pe controale (vezi react/README.md). Dacă aplicația își dă vreodată un nume propriu pentru banda de selecție, exempțiunea se înlocuiește cu `role_name`. |
Gramatica familiilor de status
Fiecare familie primește aceleași patru sloturi, ca să nu fie nimic de ținut minte per familie:
--<familie> fill saturat — text alb pe el --<familie>-foreground albul acela --<familie>-subtle tint-ul --<familie>-subtle-foreground textul pe tint
Familii: error, warning, success, read, ai. ai are doar trei sloturi, deliberat — --c-ai trece AA ca text pe toate suprafețele DS (cel mai prost caz 5.11), deci nu-i trebuie token de text separat și nu se bate unul „pentru simetrie". Excepția e acum vizibilă în nume, nu îngropată într-un anti-pattern.
Unde shadcn nu ajunge
- shadcn nu are familii de status. Livrează
--destructiveși nimic altceva. Bono are cinci. Deci nu adoptăm lista de tokene shadcn — adoptăm gramatica (rol +-foreground) și o extindem. --destructivenu e roșu. La Bono acțiunea distructivă e neagră (--c-danger, ink), iar roșul e rezervat mesageriei de eroare (--error). În shadcn cele două sunt același token. Aici sunt două, și nu sunt niciodată interschimbabile.- Feedback-ul rămâne pe numele Bono. shadcn are doar
Alert(inline) plus toast; nu are nicio primitivă de banner la nivel de pagină. Cele trei niveluri Bono —.alertinline,.bannerla nivel de pagină/flow,.page-bannerglobal — sunt mai bogate decât convenția, deci convenția cedează. Vezidocs/feedback.md. --placeholder,--separator*,--input-tonal,--overlay*sunt extensii locale: roluri reale în Bono pentru care shadcn nu are nume.
Invariantul
Fiecare token cu semantică are ori role_name, ori role_name_exempt cu un motiv scris. Nu ambele, niciodată niciunul. Două tokene nu pot revendica același nume de rol.
Consecința e cea care contează: un token nou nu poate intra în sistem fără ca cineva să decidă în ce limbaj trăiește. Garda e scripts/build-naming-dictionary.py --check, în CI lângă celelalte. Dacă pagina rămâne în urmă față de JSON, CI-ul pică — la fel ca foundation-colors.html, care a rămas în urmă de două ori exact pentru că își scria valorile de mână.