Powierzchnie, obrysy i głębia
Techniczny: DraftAkceptacja: DraftPowierzchnia to cztery decyzje naraz: tło, granica, promień i cień. System daje
na nie cztery rodziny tokenów i jedną twardą regułę: granicę komponentu rysujemy
na color.border.strong, nigdy na color.border.default. Reszta układa się
z tego, co robią dziś Card, Input, Button i Badge.
Stos teł
Dział zatytułowany „Stos teł”| Podgląd | Rola (token) | Zmienna CSS | Klasa Tailwind | Hex — light | Hex — dark |
|---|---|---|---|---|---|
color.background.page | --color-background-page | bg-background-page | #F8F9FB | #0B1326 | |
color.background.surface | --color-background-surface | bg-background-surface | #FFFFFF | #1C2430 | |
color.background.inverse | --color-background-inverse | bg-background-inverse | #0B1326 | #FFFFFF |
background.pageto tło strony.background.surfaceto tło wszystkiego, co leży na stronie: karty, kontrolki (Input, Buttonsecondary, Badgeneutral) i elementu unoszącego się nad treścią.background.inverseto sekcja odwrócona względem trybu, razem zcolor.text.inverse.
Powierzchnie są dwie, nie trzy. Osobnej roli na element uniesiony nie ma:
background.surface niesie zarówno to, co leży na stronie, jak i to, co się nad
nią unosi. Dwie nazwy na jedną barwę nie dają dwóch poziomów.
Uniesienie nie jest więc stopniem koloru. Niosą je cień w trybie jasnym i obrys w trybie ciemnym (niżej, „Cienie”). Karta nie opiera się na samym tle.
Warstwy nie mnożymy. Poziomy są dwa: treść leży na stronie albo unosi się nad
nią. Kartę w karcie zastępuje zmiana tła na background.page wewnątrz kontenera,
a nie druga karta z własnym cieniem (Card).
Stan :hover przycisku w wariancie secondary cofa tło o poziom, z surface
na page. Zmiana w stosie teł niesie tu informację o stanie, nie dekorację.
Granica komponentu
Dział zatytułowany „Granica komponentu”Komponent rysuje granicę na color.border.strong. color.border.default
zostaje separatorem dekoracyjnym; dziś używa go obrys Badge w wariancie
neutral i linie w interfejsie tej dokumentacji.
| Podgląd | Rola (token) | Zmienna CSS | Klasa Tailwind | Hex — light | Hex — dark |
|---|---|---|---|---|---|
color.border.default | --color-border-default | border-border-default | #D2D8E2 | #667080 | |
color.border.strong | --color-border-strong | border-border-strong | #667080 | #AEB6C2 | |
color.border.focus | --color-border-focus | border-border-focus | #355F92 | #6F96C2 |
Granica komponentu mówi, dokąd sięga kontrolka, więc podlega WCAG 2.2 SC 1.4.11
i potrzebuje kontrastu 3:1. border.default tego progu nie gwarantuje i stoi
świadomie poza bramką kontrastu. border.strong mierzy bramka
tokens/src/artifact.ts, i to na obu tłach, na których komponenty naprawdę stoją:
background.page i background.surface, w każdej z dziesięciu kombinacji
marki i trybu.
Wyjątek dla border.default obowiązuje tylko dopóki komponenty trzymają się
tego podziału. Granica komponentu przeniesiona na ten token nie zapali bramki,
bo bramka go nie mierzy, a kontrast i tak zniknie.
Promienie
Dział zatytułowany „Promienie”| Token | Zmienna CSS | Wartość | Podgląd | Klasa Tailwind | Przeznaczenie |
|---|---|---|---|---|---|
radius.full | --radius-full | 9999px | rounded-full | Pigułka: Badge. | |
radius.xl | --radius-xl | 16px | rounded-xl | Bez konsumenta dzisiaj. | |
radius.lg | --radius-lg | 12px | rounded-lg | Kontener treści: Card, panel. | |
radius.md | --radius-md | 8px | rounded-md | Kontrolka: Button, Input. | |
radius.sm | --radius-sm | 4px | rounded-sm | Drobny element: próbka koloru, przycisk paska narzędzi. |
Promień wynika z rangi elementu, nie z jego rozmiaru: kontrolka dostaje
radius.md, kontener treści radius.lg, element w kształcie pigułki
radius.full. Wartości nie zmieniają się z marką ani trybem, więc ten sam
komponent ma identyczny kształt we wszystkich pięciu portalach.
| Token | Zmienna CSS | Wartość | Podgląd | Klasa Tailwind | Przeznaczenie |
|---|---|---|---|---|---|
shadow.lg | --shadow-lg | 0 12px 32px rgba(16, 26, 46, 0.16) | shadow-lg | Bez konsumenta dzisiaj; rola dla warstwy nad stroną. | |
shadow.md | --shadow-md | 0 4px 12px rgba(16, 26, 46, 0.12) | shadow-md | Bez konsumenta dzisiaj; rola dla elementu nad treścią. | |
shadow.sm | --shadow-sm | 0 1px 2px rgba(16, 26, 46, 0.08) | shadow-sm | Karta leżąca na stronie (Card). |
Cień dokłada się do stosu teł, nie zastępuje go. Karta leżąca na stronie bierze
shadow.sm razem z tłem surface i obrysem border.strong. shadow.md
i shadow.lg czekają na pierwszy element unoszący się nad treścią; w ui/
nie ma go dzisiaj.
W trybie ciemnym cień nie jest nośnikiem uniesienia. Wszystkie trzy cienie
to ten sam półprzezroczysty granat (rgba(16, 26, 46, …)), czyli barwa bliska
tłu strony: shadow.lg złożony ze swoim kryciem na background.page daje
1,01:1. Tego nie widać. W trybie jasnym cień pracuje i zostaje — ta sama warstwa
na tle strony daje tam 1,39:1, czyli widoczną różnicę na jasnym podłożu.
W trybie ciemnym uniesienie niosą dwie rzeczy: różnica tła (karta wobec strony,
navy.800 na navy.900 — 1,18:1) i obrys. Pracuje obrys. Granica Card stoi
na border.strong i daje 7,64:1 wobec tła karty oraz 9,05:1 wobec tła strony;
nawet dekoracyjny border.default daje tam 3,12:1, czyli więcej niż tło i cień
razem. Dlatego element uniesiony w trybie ciemnym zawsze ma obrys, a cień jest
w nim dekoracją. Cień nigdy nie jest jedynym nośnikiem granicy — w żadnym
z dwóch trybów.
Grubość obrysu i pierścień fokusu
Dział zatytułowany „Grubość obrysu i pierścień fokusu”| Token | Zmienna CSS | Wartość | Podgląd | Przeznaczenie |
|---|---|---|---|---|
border-width.focus | --border-width-focus | 2px | Pierścień :focus-visible, grubość i odsunięcie. | |
border-width.hairline | --border-width-hairline | 1px | Obrys i separator we własnym CSS. |
Te dwa tokeny służą własnemu CSS, na przykład globals.css paczki ui
i stylom tej dokumentacji. Tailwind ich nie dostaje: theme.css rejestruje
kolor, typografię, odstępy, promienie i cienie, ale nie grubość obrysu. Klasa
border w komponencie niesie więc domyślną grubość Tailwinda, równą dziś
wartości border-width.hairline.
Pierścień :focus-visible ustawia globals.css jeden raz dla całej paczki,
z border-width.focus i focus.ring. Komponent go nie powtarza i nie wygasza.
Wymagania dla fokusu opisuje
standard dostępności.
Przykład i kontrprzykład
Dział zatytułowany „Przykład i kontrprzykład”// Tak: gotowy komponent niesie komplet decyzji o powierzchni<Card> <CardHeader> <CardTitle as="h2">OC zawodowe</CardTitle> <CardDescription>Zakres, cena i ograniczenie</CardDescription> </CardHeader> <CardContent>…</CardContent></Card>// Nie<article className="border border-border-default bg-background-surface" style={{ borderRadius: "10px", boxShadow: "0 2px 6px rgba(0, 0, 0, 0.2)" }}> …</article>Kontrprzykład psuje trzy rzeczy naraz: rysuje granicę komponentu na tokenie dekoracyjnym, wpisuje promień spoza skali i dokłada własny cień zamiast wybrać poziom z systemu. Kontrast granicy spadnie poniżej 3:1, a element przestanie wyglądać jak karta w pozostałych markach i trybach.
Granice
Dział zatytułowany „Granice”- Nowy poziom uniesienia to zmiana w tokenach, nie lokalny
box-shadow. - Nakładka pod modalem, przyklejony nagłówek i kolejność warstw nie mają dziś ani tokenu, ani komponentu. Nie zastępuj ich improwizacją w miejscu użycia.
- Powierzchnia nie zmienia znaczenia stanu. Błąd, ostrzeżenie i sukces niosą
role
color.status.*, opisane w kolorze.
Brief do wykonania
Dział zatytułowany „Brief do wykonania”@todo(surfaces): wykonać poniższy brief, przedstawić rezultat i dowody odbioru. Usunięcie znacznika nie jest wykonaniem zadania.
- Zakres: rozstrzygnąć cztery rzeczy, których dziś w systemie nie ma:
(1) nakładkę i tło warstwy nad stroną, czyli modal i arkusz, razem z tokenem
przyciemnienia tła i kolejnością warstw; (2) element unoszący się nad treścią
bez pełnej nakładki, czyli dropdown i popover, jako pierwszego konsumenta
shadow.md; (3) czytelność uniesienia w trybie ciemnym dla warstw NAD stroną — dla karty rozstrzyga ją obrys, dla nakładki, dropdownu i paska rozstrzygnięcia nie ma; (4) przyklejone paski, nagłówek i pasek akcji, wraz z granicą, która pojawia się przy przewijaniu. Rozstrzygnięcia zapadają na dwóch realnych ekranach: start B2B i decyzja zdrowia. - Konwencja: najpierw reguła lub gotowe zastosowanie, potem przykład i kontrprzykład, następnie granice oraz sposób sprawdzenia. Nie zastępuj materiału opisem planu jego przygotowania.
- Źródła:
tokens/src/semantic.tokens.json(opisy ról tła),tokens/README.md(decyzja 5:border.defaultpoza bramką kontrastu,border.strongw niej),tokens/src/artifact.ts(pary mierzone bramką), komponentyCard,Input,Button,Badge. - Granica swobody: możesz redagować i pokazywać istniejące ustalenia. Nowy poziom uniesienia, nowy token i zmianę wyglądu komponentu przedstaw do decyzji; nie uzupełniaj z pamięci.
Weryfikacja
Dział zatytułowany „Weryfikacja”pnpm -F @polisoteka/design-tokens check:tokens mierzy border.strong na tłach
page i surface w dziesięciu kombinacjach marki i trybu. Na surface mierzy
też tekst: text.secondary, text.link i status.danger.text.
border.default jest poza tą bramką świadomie, więc granicę komponentu
postawioną na nim wyłapuje wyłącznie review.
Przed oddaniem obejrzyj kartę i kontrolkę w trybie ciemnym: obrys musi być
widoczny bez pomocy cienia. Porównanie zrzutów i skan axe: pnpm design:audit.
Tokeny i zależności, kolor, odstępy i rytm, Card, Input, Button, Badge, standard dostępności.