Design system
Jedno źródło prawdy dla designu i kodu
Cała platforma jest zbudowana z tokenów i komponentów opisanych na tej stronie. Te same nazwy działają w Figmie, w kodzie i w rozmowie zespołu, więc przekazanie projektu nie wymaga tłumaczenia.
Kolory
Trzy rodziny: ink buduje tła i głębię, mist odpowiada za tekst, a glow, pulse, ok i danger niosą znaczenie. Komponent nigdy nie używa wartości hex wprost.
ink-950
Tło strony
ink-900
Tło paneli i kart
ink-700
Obramowania, szkielety
mist-50
Nagłówki, tekst główny
mist-300
Tekst akapitów
mist-500
Tekst pomocniczy
glow-400
Akcent, akcje główne
pulse-400
Akcent wtórny
ok-400
Sukces
danger-400
Błędy, destrukcja
Skala typograficzna
Siedem nazwanych kroków opartych o clamp(), kalibrowanych do ekranów referencyjnych: minimum każdego kroku przypada na 390 px, maksimum na 1440 px. Zwęż okno przeglądarki, a każdy wiersz poniżej płynnie zmaleje razem z resztą platformy.
Płynie, nie skacze
text-fluid-xs
Metki, podpisy, kod
Płynie, nie skacze
text-fluid-sm
Tekst pomocniczy, listy
Płynie, nie skacze
text-fluid-base
Akapity
Płynie, nie skacze
text-fluid-lg
Wyróżnione akapity, lead
Płynie, nie skacze
text-fluid-xl
Tytuły sekcji i kart
Płynie, nie skacze
text-fluid-2xl
Nagłówki stron drugorzędnych
Płynie, nie skacze
text-fluid-3xl
Nagłówki główne
Skala odstępów
Odstępy dostają tę samą dyscyplinę co tekst: jeden token clamp() zamiast pary klas z progiem, kalibrowany między 390 a 1440 px. Paski poniżej mają szerokość swojego tokenu, więc rosną razem z oknem.
p-fluid-2xs
4 → 8 px
Najmniejszy rytm, odstęp ikon
p-fluid-xs
16 → 20 px
Padding kart w demo
p-fluid-sm
20 → 24 px
Padding paneli i ramek demo
p-fluid-md
24 → 32 px
Padding dużych kart
p-fluid-lg
48 → 64 px
Pion podstron
p-fluid-xl
56 → 80 px
Pion stopki
p-fluid-2xl
64 → 96 px
Pion sekcji strony głównej
px-gutter
16 → 24 px
Marginesy strony, nie krok skali
Konfiguracja Tailwinda
Tak, to Tailwind, ale nie w domyślnym ustawieniu. W wersji 4 nie ma już pliku tailwind.config.js: konfiguracją jest blok @theme w globals.css. Ten sam plik czyta zespół i agent AI, więc nie ma drugiego źródła prawdy.
Domyślną drabinę pięciu breakpointów czyści --breakpoint-*: initial. W jej miejscu stoją trzy progi w rem, więc reagują na ustawienie rozmiaru tekstu w przeglądarce. xl i 2xl nie wróciły, bo żaden widok ich nie potrzebował.
Rozmiary pochodzą z tokenów, nie z progów. Dlatego cały arkusz stylów zamyka się w ośmiu blokach @media z progiem szerokości, a te pilnują wyłącznie struktury całej strony. Przełączniki w środku komponentów przeszły na container queries: sześć progów, każdy równy minimalnej szerokości treści, którą przełącza.
- 01
Token płynny
Rozmiar tekstu, padding i marginesy strony biorą clamp() z tokenu. Wartość rośnie z każdym pikselem szerokości, więc nie ma martwej strefy, w której layout jest już ciasny, a skala jeszcze duża.
text-fluid-lg, p-fluid-md, px-gutter
- 02
Container query
Komponent pyta swój kontener, nie ekran, więc działa w każdym miejscu, do którego go przeniesiesz. Tak przełącza się tu tabela w listę kart: liczy się szerokość panelu, nie szerokość okna.
@container, @[40rem]:block, cqi
- 03
Siatka, która sama liczy kolumny
Liczba kolumn wynika z dostępnego miejsca i minimalnej szerokości karty, nie z listy progów. Jedna klasa obsługuje zegarek i monitor, a treść nigdy nie ląduje w kolumnie węższej niż czytelna.
grid-auto-sm, grid-auto-md, grid-auto-xl
- 04
Breakpoint
Ostatni szczebel i tylko dla struktury całej strony: pozioma nawigacja w menu pełnoekranowe, asymetryczny layout lekcji, sidebar checklisty. Nigdy dla rozmiaru tekstu ani rytmu odstępów. Przełącznik w środku komponentu należy do szczebla 02.
lg:flex, lg:grid-cols-[2fr_3fr], md:grid-cols-2
@import "tailwindcss";
@theme {
--breakpoint-*: initial;
--breakpoint-sm: 40rem;
--breakpoint-md: 48rem;
--breakpoint-lg: 64rem;
--color-glow-400: #45e3cb;
--text-fluid-base: clamp(1rem, 0.93rem + 0.29vw, 1.1875rem);
--text-fluid-base--line-height: 1.65;
--spacing-fluid-md: clamp(1.5rem, 1.31rem + 0.76vw, 2rem);
--spacing-gutter: clamp(1rem, 0.81rem + 0.76vw, 1.5rem);
}<article className="p-4 text-sm sm:p-5 sm:text-base lg:p-8">
<h2 className="text-lg sm:text-xl lg:text-3xl">{title}</h2>
</article><article className="p-fluid-md text-fluid-base">
<h2 className="text-fluid-2xl">{title}</h2>
</article>Komponenty
Każdy komponent ma wbudowane zachowania z zasad platformy: rezerwację miejsca na błędy, stałe wymiary w stanie ładowania i płynną typografię. Używasz go i dobre nawyki przychodzą same.
Przyciski
Włącz stan ładowania i zmierz przyciski wzrokiem. Spinner zastępuje etykietę w tej samej komórce siatki, więc wymiary nie drgną.
Pola formularza
Slot na błąd jest wbudowany w komponent, więc żaden formularz w projekcie nie może o nim zapomnieć.
Adres musi zawierać znak @.
Statusy
Pięć odcieni wystarcza na cały cykl życia projektu. Nowe kolory dodajemy do tokenów, nigdy do pojedynczego komponentu.
import { Button } from "@/components/ui/Button";
import { Input } from "@/components/ui/Input";
import { Badge } from "@/components/ui/Badge";
<Input label="Adres e-mail" error={errors.email} />
<Button loading={submitting}>Zapisz zmiany</Button>
<Badge tone="ok">Gotowe</Badge>