Guide / 16 min

Zasady projektowania dla inżynierów oprogramowania

Podstawy projektowania przydatne przy tworzeniu lepszego oprogramowania. Typografia, teoria koloru, odstępy, animacja, wzorce interfejsów AI oraz 48 produktowych studiów przypadków od Arc po Zomato.

Zaktualizowano 18 maja 2026

Aktualizacja z 18 maja 2026: Odświeżono indeks studiów projektowych, aby odpowiadał aktualnemu korpusowi 48 analiz, oraz rozszerzono wzorce interfejsów AI o dowody dotyczące przepływów agentowych: punkty kontrolne, stany zatwierdzenia, wiarygodność źródeł i widoczną weryfikację.

Aktualizacja z maja 2026: Dodano uwagę o roboczym szkicu WCAG 3.0 z marca 2026 roku oraz o stanowisku W3C, zgodnie z którym WCAG 2.2 i 3.0 będą współistnieć. WCAG 2.2 pozostaje standardem, w który należy celować przy bieżących pracach nad dostępnością.

Aktualizacja z lutego 2026: Dodano dwie nowe sekcje — wzorce interakcji (8 paradygmatów wynikających z analizy Framer, Flighty, Halide, Warp, Bear, Craft i Superhuman) oraz wzorce interfejsów AI (projektowanie z cytowaniami na pierwszym planie, fazy streamingu, przejrzystość błędów na przykładzie Perplexity). Zaktualizowano wzorce webowe na 2026 rok, uwzględniając pozycjonowanie kotwic, animacje sterowane przewijaniem i @starting-style. Zaktualizowano dostępność, aby odzwierciedlić standaryzację ISO dla WCAG 2.2. Głębokie analizy 48 wyjątkowych produktów znajdują się w sekcji studia projektowe. Przez lata, budując oprogramowanie, zgłębiałem projektowanie, przyswajając zasady od legend takich jak Dieter Rams i analizując interfejsy produktów takich jak Linear, Stripe i Raycast. Ten przewodnik destyluje tę wiedzę w kompleksowe kompendium, którego brakowało mi, gdy zacząłem zwracać uwagę na to, jak moje oprogramowanie wygląda i jakie sprawia wrażenie.

Projektowanie nie jest dekoracją. Jest komunikacją. Każdy piksel komunikuje funkcję, hierarchię i znaczenie. Różnica między oprogramowaniem, które sprawia wrażenie amatorskiego, a oprogramowaniem, które sprawia wrażenie profesjonalnego, polega na zrozumieniu tych zasad i konsekwentnym ich stosowaniu.

Ten przewodnik zakłada, że potrafi Pan/Pani już pisać kod. Uczy patrzeć — rozumieć, dlaczego niektóre interfejsy wydają się bezwysiłkowe, a inne chaotyczne, i co ważniejsze, jak tworzyć te pierwsze.


Spis treści

Część 1: Podstawy

  1. Psychologia Gestalt
  2. Typografia
  3. Teoria koloru
  4. Hierarchia wizualna
  5. Odstępy i rytm
  6. Zasady animacji

Część 2: Interakcja i AI

  1. Wzorce interakcji
  2. Wzorce interfejsów AI

Część 3: Filozofia projektowania

  1. Dieter Rams: dziesięć zasad

Część 4: Implementacja

  1. Wzorce webowe 2026
  2. System design tokens
  3. Tryb ciemny zrobiony dobrze
  4. Przepływy pracy z Figma

Część 5: Materiały referencyjne

  1. Tabele szybkiego odniesienia
  2. Lista kontrolna projektu
  3. Studia projektowe

Psychologia Gestalt

„Całość jest czymś innym niż suma jej części.” — Kurt Koffka

Psychologia Gestalt, rozwinięta w Niemczech w latach 20. XX wieku, wyjaśnia, w jaki sposób ludzie postrzegają informacje wizualne. Mózg nie widzi pojedynczych pikseli — organizuje elementy w znaczące wzorce. Opanowanie tych zasad pozwala kontrolować sposób, w jaki użytkownicy postrzegają interfejsy.

Bliskość

Elementy znajdujące się blisko siebie są postrzegane jako grupa.

To najpotężniejsza zasada Gestalt w projektowaniu UI. Przestrzeń komunikuje relacje lepiej niż jakakolwiek inna właściwość wizualna.

WRONG (equal spacing = no grouping):
┌─────────────────┐
│ Label           │
│                 │
│ Input Field     │
│                 │
│ Label           │
│                 │
│ Input Field     │
└─────────────────┘

RIGHT (unequal spacing = clear groups):
┌─────────────────┐
│ Label           │
│ Input Field     │ ← Tight (4px) - related
│                 │
│                 │ ← Wide (24px) - separating groups
│ Label           │
│ Input Field     │ ← Tight (4px) - related
└─────────────────┘

Implementacja CSS:

.form-group {
  margin-bottom: 24px;  /* Between groups: wide */
}

.form-group label {
  margin-bottom: 4px;   /* Label to input: tight */
  display: block;
}

Implementacja SwiftUI:

VStack(alignment: .leading, spacing: 4) {  // Tight within group
    Text("Email")
        .font(.caption)
        .foregroundStyle(.secondary)
    TextField("[email protected]", text: $email)
        .textFieldStyle(.roundedBorder)
}
.padding(.bottom, 24)  // Wide between groups

Podobieństwo

Elementy o wspólnych cechach wizualnych wydają się powiązane.

Gdy elementy wyglądają tak samo, użytkownicy zakładają, że działają tak samo. Dlatego systemy projektowe stosują spójne style przycisków, kart i typografii.

Example Navigation:
┌───────────────────────────────────┐
 [Dashboard] [Projects] [Settings]    Same style = same function
                                   
 ┌─────┐  ┌─────┐  ┌─────┐        
 Card   Card   Card             Same style = same content type
 └─────┘  └─────┘  └─────┘        
                                   
 [+ New Project]                      Different style = different function
└───────────────────────────────────┘

Figura i tło

Treść powinna wyraźnie oddzielać się od tła.

Mózg musi odróżnić „figurę” (obiekt, na którym się skupia) od „tła” (podłoża). Słabe relacje figura–tło wywołują chaos wizualny.

Techniki: - Kontrast (jasna figura na ciemnym tle i odwrotnie) - Cienie (unoszenie figury nad tło) - Obramowania (wyznaczanie krawędzi figury) - Rozmycie (rozmycie tła, wyostrzenie figury)

/* Strong figure-ground relationship */
.card {
  background: var(--color-surface);     /* Figure */
  border-radius: 12px;
  box-shadow: 0 1px 3px rgba(0,0,0,0.1);  /* Elevation */
}

.modal-overlay {
  background: rgba(0, 0, 0, 0.5);  /* Dim ground */
  backdrop-filter: blur(4px);      /* Blur ground */
}

Wspólny region

Elementy zawarte w granicach jednego obszaru są postrzegane jako grupa.

Umieszczenie elementów w wizualnym kontenerze (karcie, ramce, obszarze z obramowaniem) sygnalizuje, że należą do siebie.

Ciągłość

Oko podąża za ścieżkami, liniami i krzywymi.

Wyrównanie i przepływ wizualny kierują uwagę przez interfejs.

CONTINUITY IN ALIGNMENT:
┌────────────────────────────────┐
 Logo    [Nav]  [Nav]  [Nav]      Aligned on horizontal axis
├────────────────────────────────┤
                                
 Headline                       
 ─────────────────────────────     Eye follows left edge
 Paragraph text continues       
 along the same left edge       
                                
 [Primary Action]                  Still on the left edge
└────────────────────────────────┘

Domknięcie

Mózg uzupełnia niekompletne kształty.

Użytkownicy nie potrzebują narysowanego każdego piksela — mentalnie dopełniają znane kształty. Pozwala to tworzyć bardziej minimalistyczne i eleganckie projekty.

/* Horizontal scroll with partial card (closure) */
.card-carousel {
  display: flex;
  gap: 16px;
  overflow-x: auto;
  padding-right: 48px;  /* Show partial card = scroll hint */
}

.card-carousel .card {
  flex: 0 0 280px;  /* Fixed width, partial visible */
}

Gestalt — szybkie odniesienie

Zasada Reguła Główne zastosowanie
Bliskość Powiązane = blisko, niepowiązane = daleko Pola formularzy, sekcje treści
Podobieństwo Ten sam wygląd = ta sama funkcja Przyciski, karty, nawigacja
Figura i tło Wyraźne rozdzielenie warstw Karty, modale, nakładki
Wspólny region Granice grupują treść Sekcje ustawień, karty użytkowników
Ciągłość Podążanie za liniami i wyrównaniem Osie czasu, przepływ czytania
Domknięcie Mózg uzupełnia kształty Ikony, wskazówki przewijania, szkielety

Typografia

„Typografia to sztuka nadawania ludzkiemu językowi trwałej formy wizualnej.” — Robert Bringhurst

Typografia stanowi fundament projektowania interfejsów. Tekst komunikuje funkcjonalność, hierarchię i tożsamość marki. Słaba typografia utrudnia korzystanie z interfejsów; świetna typografia jest niewidoczna — po prostu działa.

Skala typograficzna

Spójna skala tworzy wizualną harmonię. Warto stosować proporcję matematyczną.

Skala 1,25 (zalecana dla UI):

:root {
  /* Base: 16px (1rem) */
  --text-xs: 0.64rem;    /* 10.24px - use sparingly */
  --text-sm: 0.8rem;     /* 12.8px - captions, labels */
  --text-base: 1rem;     /* 16px - body text */
  --text-lg: 1.25rem;    /* 20px - lead text */
  --text-xl: 1.563rem;   /* 25px - h4 */
  --text-2xl: 1.953rem;  /* 31.25px - h3 */
  --text-3xl: 2.441rem;  /* 39px - h2 */
  --text-4xl: 3.052rem;  /* 48.8px - h1 */
}

Interlinia (leading)

Interlinia ma ogromny wpływ na czytelność. Różne rodzaje treści wymagają różnej interlinii.

Typ treści Interlinia Dlaczego
Nagłówki 1,1–1,2 Zwięzłe, pogrubione, krótkie
Tekst UI 1,3–1,4 Etykiety, przyciski
Tekst główny 1,5–1,7 Czytelne akapity
Teksty długie 1,7–2,0 Artykuły, dokumentacja

Długość wiersza (miara)

Optymalna długość wiersza zapobiega zmęczeniu oczu i poprawia zrozumienie tekstu.

  • Optimum: 45–75 znaków na wiersz
  • Cel: 50–65 znaków
  • Absolutne maksimum: 85 znaków
p {
  max-width: 65ch;  /* ch unit = width of '0' character */
}

.article-body {
  max-width: 70ch;
  margin: 0 auto;
}

Dobór kroju pisma

Najpierw czcionki systemowe. Ładują się natychmiast, pasują do platformy i są zoptymalizowane pod kątem ekranów.

:root {
  --font-sans: system-ui, -apple-system, BlinkMacSystemFont,
               'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;

  --font-mono: ui-monospace, 'SF Mono', 'Cascadia Code',
               'JetBrains Mono', Consolas, monospace;
}

Czcionki niestandardowe sprawdzają się w przypadku: - Wyróżnienia marki (strony marketingowe) - Charakteru edytorskiego / wydawniczego - Konkretnej intencji projektowej nieosiągalnej za pomocą czcionek systemowych

Grubość kroju w hierarchii

Grubość kroju pozwala budować hierarchię, nie tylko sam rozmiar.

h1 { font-weight: 700; }  /* Bold */
h2 { font-weight: 600; }  /* Semibold */
h3 { font-weight: 600; }  /* Semibold */
.lead { font-weight: 500; }  /* Medium */
p { font-weight: 400; }   /* Regular */
.meta { font-weight: 400; color: var(--text-muted); }

Typografia — szybkie odniesienie

Właściwość Tekst główny Nagłówki Etykiety UI
Rozmiar 16–18px 24–48px 12–14px
Grubość 400 600–700 500
Interlinia 1,5–1,7 1,1–1,2 1,3–1,4
Długość wiersza 45–75ch nie dotyczy nie dotyczy
Wyrównanie Do lewej Wyśrodkowanie OK Do lewej

Teoria koloru

„Kolor jest siłą, która bezpośrednio wpływa na duszę.” — Wassily Kandinsky

Kolor komunikuje szybciej niż słowa. Buduje nastrój, kieruje uwagę, sygnalizuje znaczenie i wzmacnia rozpoznawalność marki.

Reguła 60-30-10

Najbardziej niezawodny rozkład kolorów w zrównoważonych interfejsach.

┌──────────────────────────────────────────┐
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│ 60% - Dominant (Background)
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
│░░░░░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░░░│ 30% - Secondary (Cards, sections)
│░░░░░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░░░│
│░░░░░▓▓▓▓▓▓▓▓▓▓▓▓██████▓▓▓▓▓▓▓▓▓▓░░░░░░░░│ 10% - Accent (Buttons, links)
└──────────────────────────────────────────┘

Tworzenie palety kolorów

Każdy interfejs potrzebuje następujących kolorów semantycznych:

:root {
  /* Brand */
  --color-primary: hsl(220, 80%, 50%);
  --color-primary-hover: hsl(220, 80%, 45%);

  /* Semantic */
  --color-success: hsl(142, 76%, 36%);  /* Green - positive */
  --color-warning: hsl(38, 92%, 50%);   /* Amber - caution */
  --color-error: hsl(0, 84%, 60%);      /* Red - danger */

  /* Neutrals */
  --color-background: hsl(0, 0%, 100%);
  --color-surface: hsl(220, 14%, 96%);
  --color-border: hsl(220, 13%, 91%);

  /* Text */
  --color-text: hsl(220, 13%, 13%);
  --color-text-secondary: hsl(220, 9%, 46%);
  --color-text-muted: hsl(220, 9%, 64%);
}

Psychologia koloru

Kolor Psychologia Zastosowanie w UI
Niebieski Zaufanie, stabilność, spokój Finanse, technologia, rozwiązania korporacyjne
Zielony Wzrost, natura, sukces Zdrowie, ekologia, stany pozytywne
Czerwony Energia, pilność, zagrożenie Alerty, sprzedaż, błędy
Pomarańczowy Ciepło, entuzjazm CTA, marki o swobodnym charakterze
Żółty Optymizm, ostrożność Ostrzeżenia, wyróżnienia
Fioletowy Luksus, kreatywność Produkty premium
### Projektowanie z pierwszeństwem trybu ciemnego (Vercel)
Vercel projektuje najpierw z myślą o trybie ciemnym, a następnie wyprowadza z niego tryb jasny. Dzięki temu powstają lepsze ciemne interfejsy, ponieważ tryb ciemny staje się głównym założeniem, a nie dodatkiem na później.
/* Design dark first, derive light */
:root {
  /* Dark mode defaults */
  --color-background: hsl(0, 0%, 0%);
  --color-surface: hsl(0, 0%, 7%);
  --color-border: hsl(0, 0%, 15%);
  --color-text: hsl(0, 0%, 93%);
  --color-text-secondary: hsl(0, 0%, 63%);
}

@media (prefers-color-scheme: light) {
  :root {
    --color-background: hsl(0, 0%, 100%);
    --color-surface: hsl(0, 0%, 97%);
    --color-border: hsl(0, 0%, 89%);
    --color-text: hsl(0, 0%, 9%);
    --color-text-secondary: hsl(0, 0%, 40%);
  }
}

Kiedy stosować: Narzędzia programistyczne, aplikacje multimedialne, pulpity nawigacyjne — konteksty, w których użytkownicy spędzają długie sesje, a tryb ciemny zmniejsza zmęczenie oczu.

Kontrast dostępności

Poziom Zwykły tekst Duży tekst Komponenty UI
AA 4.5:1 3:1 3:1
AAA 7:1 4.5:1 Nie dotyczy
WCAG 2.2 stał się standardem ISO (ISO/IEC 40500:2025) w październiku 2025 roku, dodając kryteria dotyczące widoczności fokusu, redundantnego wprowadzania danych i dostępnego uwierzytelniania. Najważniejsze dodatki: wskaźniki fokusu nie mogą być całkowicie zasłonięte przez inne treści (2.4.11), a uwierzytelnianie nie może opierać się wyłącznie na testach funkcji poznawczych (3.3.8). W3C opublikowało zaktualizowany WCAG 2.2 w grudniu 2024 roku; oczekuje się, że zostanie wydany jako ISO/IEC 40500:2026 pod koniec 2026 roku.

WCAG 3.0 nadal jest wersją roboczą. Najnowsza rewizja została opublikowana w marcu 2026 roku i nie zastępuje WCAG 2.2; W3C podaje, że oba standardy będą współistnieć. Accessibility Guidelines Working Group planuje opublikować przewidywany harmonogram WCAG 3 w 2026 roku, ale WCAG 2.2 pozostaje standardem, do którego należy dążyć w bieżących pracach.

Narzędzia: WebAIM Contrast Checker, selektor kolorów Chrome DevTools


Hierarchia wizualna

„Design jest cichym ambasadorem marki.” — Paul Rand

Hierarchia wizualna kontroluje, co użytkownicy widzą jako pierwsze, drugie i trzecie. Bez wyraźnej hierarchii użytkownicy muszą wkładać wysiłek w znalezienie informacji. Dzięki niej interfejsy wydają się intuicyjne.

Sześć narzędzi hierarchii

1. Rozmiar — Większe elementy jako pierwsze przyciągają uwagę

.hero-title { font-size: 3rem; }      /* Dominant */
.section-title { font-size: 1.5rem; } /* Secondary */
.body-text { font-size: 1rem; }       /* Baseline */

2. Grubość — Pogrubienie wysuwa się na pierwszy plan, lekki krój się cofa

h1 { font-weight: 700; }
.lead { font-weight: 500; }
p { font-weight: 400; }

3. Kolor i kontrast — Wysoki kontrast = przyciągnięcie uwagi

.title { color: var(--color-text); }  /* Near black */
.meta { color: var(--color-text-muted); }  /* Gray */

4. Pozycja — Kluczowe pozycje mają znaczenie

F-PATTERN (content pages):     Z-PATTERN (landing pages):
████████████████████████      1 ──────────────────► 2
████████                            ↘
████                                     ↘
██                                            ↘
                                   3 ──────────────────► 4

5. Pusta przestrzeń — Izolacja nadaje znaczenie

.hero { padding: 120px 48px; }  /* Generous space */
.data-table { padding: 12px; }  /* Dense content */

6. Głębia i wyniesienie — Elementy wysunięte na pierwszy plan domagają się uwagi

:root {
  --shadow-sm: 0 1px 2px rgba(0,0,0,0.05);
  --shadow-md: 0 4px 6px rgba(0,0,0,0.1);
  --shadow-lg: 0 10px 15px rgba(0,0,0,0.1);
}

.card { box-shadow: var(--shadow-sm); }
.card:hover { box-shadow: var(--shadow-md); }
.modal { box-shadow: var(--shadow-lg); }

Zastosowane wzorce

Obecność współpracowników (Figma): Kursory wielu użytkowników z etykietami nazw, podświetleniami zaznaczeń i obrysami komponentów tworzą żywy dokument. Kolor każdego współpracownika jest odrębny, ale ma tę samą wagę wizualną - żaden kursor nie jest „głośniejszy” od innego.

Dyskretne wskaźniki statusu (Vercel): Status wdrożenia wykorzystuje subtelne, stałe wskaźniki zamiast natarczywych alertów. Cienki kolorowy pasek u góry komunikuje stan (trwa budowanie, wdrożono, niepowodzenie) bez przerywania pracy.

Analogie projektowe ze świata rzeczywistego (Flighty): Wizualizacje postępu lotu nawiązują do fizycznych przyrządów lotniczych - krzywe wysokości, wskaźniki prędkości i mapy bramek wykorzystują znane metafory wizualne zamiast abstrakcyjnych pasków postępu.

Test mrużenia oczu

Warto zmrużyć oczy, patrząc na projekt. Czy hierarchia nadal jest widoczna? Jeśli tak, jest silna.


Odstępy i rytm

„Biała przestrzeń jest jak powietrze: jest niezbędna, aby projekt mógł oddychać.” — Wojciech Zieliński

Odstępy są niewidoczną strukturą designu. Spójne odstępy tworzą wizualny rytm — poczucie, że elementy należą do siebie w ramach spójnego systemu.

Siatka 8 px

Siatka 8 px jest standardem branżowym, ponieważ: - Dzieli się równomiernie (8, 16, 24, 32, 40, 48…) - Działa z typowymi gęstościami ekranów (1x, 1.5x, 2x, 3x) - Tworzy spójny rytm bez obliczeń

:root {
  --space-1: 4px;    /* Tight: icon gaps */
  --space-2: 8px;    /* Compact: inline elements */
  --space-3: 12px;   /* Snug: form fields */
  --space-4: 16px;   /* Default: most gaps */
  --space-6: 24px;   /* Spacious: card padding */
  --space-8: 32px;   /* Section gaps */
  --space-12: 48px;  /* Major sections */
  --space-16: 64px;  /* Page sections */
  --space-20: 80px;  /* Hero spacing */
}

Odstępy wewnętrzne i zewnętrzne

Wewnętrzne (padding): Przestrzeń wewnątrz elementu Zewnętrzne (margin): Przestrzeń między elementami

Zasada: Odstępy wewnętrzne zwykle powinny być większe niż odstępy zewnętrzne w powiązanych grupach.

.card {
  padding: 24px;        /* Internal: spacious */
  margin-bottom: 16px;  /* External: less than padding */
}

Wzorce odstępów w komponentach

Karty:

.card { padding: 24px; border-radius: 12px; }
.card-header { margin-bottom: 16px; }
.card-title { margin-bottom: 4px; }  /* Tight to subtitle */

Przyciski:

.btn { padding: 12px 24px; border-radius: 8px; }
.btn--sm { padding: 8px 16px; }
.btn--lg { padding: 16px 32px; }
.btn-group { display: flex; gap: 12px; }

Formularze:

.form-row { margin-bottom: 24px; }
.form-label { margin-bottom: 4px; }
.form-help { margin-top: 4px; }
.form-actions { margin-top: 32px; display: flex; gap: 12px; }

Szybkie zestawienie odstępów

Kontekst Zalecany odstęp
Ikona do tekstu 4-8px
Etykieta do pola 4px
Między grupami formularza 24px
Padding karty 20-24px
Odstęp między kartami 16-24px
Padding sekcji (mobile) 48-64px
Padding sekcji (desktop) 80-96px
Padding przycisku (poziomo/pionowo) 24px / 12px

Zasady animacji

„Animation is not the art of drawings that move but the art of movements that are drawn.” — Norman McLaren

Animacja ożywia interfejsy. Dobrze wykonana kieruje uwagę, komunikuje stan i tworzy emocjonalną więź. Źle wykonana — frustruje i rozprasza.

Zasada nadrzędna

Animacja powinna wydawać się nieunikniona, nie dekoracyjna.

Dobra animacja: 1. Komunikuje coś, czego statyczny projekt nie jest w stanie przekazać 2. Zmniejsza obciążenie poznawcze, pokazując relacje między elementami 3. Wydaje się naturalna i oczekiwana 4. Znika ze świadomej percepcji

Zła animacja: 1. Istnieje tylko dlatego, że „fajnie wygląda” 2. Spowalnia użytkownika 3. Przyciąga uwagę na siebie 4. Wywołuje niepokój lub niecierpliwość

Kluczowe zasady dla UI

1. Antycypacja — przygotowanie użytkownika na to, co nadchodzi.

.button {
  transition: transform 0.1s ease-out;
}

.button:active {
  transform: scale(0.97);  /* Slight press before action */
}

2. Kontynuacja ruchu — ruch powinien zakończyć się naturalnie, z efektem sprężystego wygaszania.

.panel {
  transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}
withAnimation(.spring(response: 0.4, dampingFraction: 0.7)) {
    isOpen = true
}

3. Ease-In, Ease-Out — nic w naturze nie porusza się ze stałą prędkością.

Krzywa Zastosowanie Charakter
ease-out Elementy wchodzące Szybki start, łagodne zatrzymanie
ease-in Elementy wychodzące Łagodny start, szybkie wyjście
ease-in-out Zmiany stanu Płynność przez cały czas trwania
linear Wskaźniki ładowania Ciągły, mechaniczny ruch

4. Inscenizacja — kierowanie uwagi na to, co istotne. W danym momencie powinien poruszać się tylko jeden element, chyba że ruch jest choreografowany jako grupa.

5. Kaskadowe pojawianie się — elementy powinny pojawiać się sekwencyjnie, nie wszystkie naraz.

.list-item {
  animation: fadeSlideIn 0.3s ease-out both;
}

.list-item:nth-child(1) { animation-delay: 0ms; }
.list-item:nth-child(2) { animation-delay: 50ms; }
.list-item:nth-child(3) { animation-delay: 100ms; }
.list-item:nth-child(4) { animation-delay: 150ms; }

@keyframes fadeSlideIn {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}

Wytyczne dotyczące czasu trwania

Czas trwania Zastosowanie Odczucie
50–100ms Mikrointerakcje (najechanie, naciśnięcie) Natychmiastowa reakcja
150–200ms Proste zmiany stanu (przełącznik, zaznaczenie) Żwawe
250–350ms Średnie przejścia (wysunięcie panelu, obrót karty) Płynne
400–500ms Duże ruchy (przejścia między stronami, modale) Celowe, świadome

Wydajność — złota zasada

Animuj wyłącznie transform i opacity — są GPU i nie wyzwalają przeliczania układu.

/* BAD: Animating layout */
.panel { transition: left 0.3s, width 0.3s; }

/* GOOD: Using transform */
.panel { transition: transform 0.3s; }

Kiedy NIE animować

  1. Użytkownik włączył prefers-reduced-motion css @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; } }

  2. Animacja nie wnosi informacji — zbędne kółka ładowania, podskakujące elementy

  3. Użytkownik się spieszy — stany błędów, walidacja formularzy, wyniki wyszukiwania
  4. Animacja spowalniałaby powtarzane czynności — skróty klawiaturowe powinny pomijać animacje
  5. Dane są już załadowane — Bear wykorzystuje wstępne ładowanie treści, eliminując stany ładowania i sprawiając, że aplikacja działa natychmiastowo. Jeśli można wstępnie załadować dane, warto pominąć szkielety i wskaźniki ładowania.
// Bear's approach: preload so no loading state is needed
struct NoteListView: View {
    @Query var notes: [Note]  // SwiftData loads from disk instantly
    // No loading state, no skeleton, no spinner — data is always there
    var body: some View {
        List(notes) { note in
            NoteRow(note: note)
        }
    }
}

Szybka ściągawka z animacji

:root {
  /* Durations */
  --duration-instant: 0.1s;
  --duration-fast: 0.15s;
  --duration-normal: 0.25s;
  --duration-slow: 0.4s;

  /* Easings */
  --ease-out: cubic-bezier(0.0, 0.0, 0.58, 1.0);
  --ease-in: cubic-bezier(0.42, 0.0, 1.0, 1.0);
  --ease-in-out: cubic-bezier(0.42, 0.0, 0.58, 1.0);
  --ease-out-back: cubic-bezier(0.34, 1.56, 0.64, 1);
}

Wzorce interakcji

„The best interface is no interface.” — Golden Krishna

Wzorce interakcji definiują, w jaki sposób użytkownicy manipulują produktem, nawigują po nim i go rozumieją. Przedstawione tu wzorce zostały wyodrębnione na podstawie analizy produktów oferujących wyjątkowe interakcje.

Bezpośrednia manipulacja (Framer)

Abstrakcyjne koncepcje warto uczynić namacalnymi. Framer przekształca CSS — abstrakcyjne wartości liczbowe — w przeciągane uchwyty. Użytkownicy widzą, jak układ adaptuje się w czasie rzeczywistym.

/* Breakpoint handle styling */
.breakpoint-handle {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 4px;
  background: var(--accent);
  cursor: col-resize;
  opacity: 0.6;
  transition: opacity 0.15s ease;
}

.breakpoint-handle:hover,
.breakpoint-handle:active {
  opacity: 1;
  width: 6px;
}

Kiedy stosować: wszędzie tam, gdzie wynik jest wizualny — przeciąganie w celu zmiany rozmiaru, selektory kolorów, przewijanie osi czasu.

Interfejsy kontekstowe (Flighty, Figma)

Wyświetlanie wyłącznie tego, co jest istotne w danym momencie. Flighty wykorzystuje 15 odrębnych stanów do śledzenia lotów. Panel właściwości w Figma całkowicie się zmienia w zależności od tego, co zostało zaznaczone.

Faza (Flighty) Co widzi użytkownik
24 godz. przed Kod potwierdzenia, informacje o terminalu
Na lotnisku Numer bramki, godzina boardingu
W trakcie lotu Pozostały czas, postęp, szacowany czas przylotu
Lądowanie Bramki przesiadkowe, trasa dojścia
enum ContextState: CaseIterable {
    case farOut, dayBefore, headToAirport, atAirport
    case atGate, boarding, inFlight, landed, connection

    static func current(for flight: Flight, context: UserContext) -> ContextState {
        // Factor in: time, location, flight status
        // Return the single most relevant state
    }
}

Antywzorzec: wyświetlanie wszystkich kontrolek i wyszarzanie nieistotnych. Tworzy to szum wizualny.

Inteligentna aktywacja (Halide)

Narzędzia powinny rozpoznawać kontekst i aktywować się samodzielnie. Lupa ostrości w Halide pojawia się przy przeciąganiu fokusu i znika po zwolnieniu. Nie potrzeba żadnych przycisków przełączania.

struct IntelligentlyActivated<Content: View>: ViewModifier {
    let isInteracting: Bool
    @State private var isVisible = false

    func body(content: Content) -> some View {
        content
            .opacity(isVisible ? 1 : 0)
            .scaleEffect(isVisible ? 1 : 0.95)
            .animation(.easeInOut(duration: 0.2), value: isVisible)
            .onChange(of: isInteracting) { _, newValue in
                if newValue {
                    withAnimation { isVisible = true }
                } else {
                    DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
                        if !isInteracting { isVisible = false }
                    }
                }
            }
    }
}

Projektowanie dwutrybowe (Halide, Warp)

Zmiana trybu powinna transformować UI, nie tylko przełączać elementy. Tryby Auto i Manual w Halide to zupełnie różne interfejsy. Warp łączy CLI i GUI za pomocą czterech metod wprowadzania danych (wpisywanie, paleta poleceń, AI, mysz), nie zmuszając użytkowników do jednego paradygmatu.

Treść ustrukturyzowana (Warp, Bear, Craft)

Nadawanie struktury tradycyjnie nieustrukturyzowanym treściom. Warp zamienia wyjście terminala w dyskretne bloki, które można kopiować, udostępniać lub ponownie uruchamiać. Bear pozwala organizować notatki w trakcie pisania (#tag/subtag). W Craft każdy blok może stać się stroną — struktura wyłania się z użytkowania, nie z predefiniowanej hierarchii.

Stopniowe szkolenie (Superhuman)

Uczenie użytkowników szybszych metod poprzez powtarzalną ekspozycję. Paleta Cmd+K w Superhuman zawsze wyświetla skróty klawiaturowe obok wyników. Każde użycie to mikrolekcja.

/* Always show shortcut alongside command name */
.command-result {
  display: flex;
  justify-content: space-between;
  padding: 8px 12px;
}

.command-shortcut {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text-muted);
  background: var(--bg-subtle);
  padding: 2px 6px;
  border-radius: 4px;
}

Antywzorzec: modalne okna z samouczkiem wyjaśniające funkcje. Wyjaśnienia się zapomina — praktyka zostaje w pamięci.

Wzorce interfejsów AI

„Najlepsze interfejsy AI pokazują proces działania maszyny i pozwalają zweryfikować jej wyniki”.

Interfejsy AI mierzą się z wyjątkowymi wyzwaniami: użytkownicy nie mogą przewidzieć wyniku, nie mogą zweryfikować dokładności samą inspekcją i często nie potrafią stwierdzić, czy system działa, czy jest uszkodzony.

Główny problem

Tradycyjne oprogramowanie Oprogramowanie AI
Wynik jest przewidywalny Wynik się zmienia
Błędy są oczywiste Błędy wyglądają wiarygodnie
Użytkownicy weryfikują przez testowanie Użytkownicy weryfikują przez sprawdzanie źródeł
Ładowanie = oczekiwanie Ładowanie = praca systemu (należy ją pokazać)
Zaufanie domyślne Na zaufanie trzeba zasłużyć
### Projektowanie z cytowaniami na pierwszym planie (Perplexity)
Każde twierdzenie faktograficzne musi zawierać link do źródła. Perplexity osadza cytowania inline [1] przy każdym twierdzeniu, z podglądem po najechaniu kursorem i stałym panelem źródeł.
.citation-marker {
  position: relative;
  color: var(--accent);
  cursor: pointer;
  font-size: 0.8em;
  vertical-align: super;
}

.citation-preview {
  position: absolute;
  bottom: 100%;
  left: 50%;
  transform: translateX(-50%);
  width: 280px;
  padding: 12px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

Antywzorzec: interfejsy AI, które generują twierdzenia bez możliwych do prześledzenia źródeł. Jeśli model nie potrafi podać źródła, interfejs powinien to oznaczyć.

Wskaźniki faz strumieniowania (Perplexity)

Należy pokazywać użytkownikom, co robi AI, a nie tylko to, że pracuje. Ogólne wskaźniki ładowania warto zastąpić wskaźnikami faz: „Wyszukiwanie…” → „Czytanie 4 źródeł…” → „Pisanie odpowiedzi…”

.phase-indicator {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  background: color-mix(in srgb, var(--phase-color) 10%, transparent);
  border-radius: 16px;
  font-size: 13px;
  color: var(--phase-color);
  transition: all 0.3s ease;
}

.loading-dots span {
  width: 4px;
  height: 4px;
  background: currentColor;
  border-radius: 50%;
  animation: pulse 1.4s ease-in-out infinite;
}

Przejrzystość błędów

Gdy AI zawodzi lub nie ma pewności, należy pokazać to wyraźnie — bez ukrywania się za tekstem brzmiącym pewnie.

Sytuacja Zły wzorzec Dobry wzorzec
Niska pewność Stwierdzenie tego pewnym tonem „Nie mam pewności, ale…” w mniej wyrazistym stylu
Nie znaleziono źródeł Wymyślenie tekstu „Nie udało mi się znaleźć źródeł dla tego twierdzenia”
Sprzeczne źródła Wybranie jednego bez informowania Pokazanie obu z wyróżnioną sprzecznością
Nieaktualne informacje Przedstawienie jako aktualnych „Stan na [data]…” ze wskaźnikiem aktualności
Kluczowa obserwacja: Użytkownicy wybaczają AI, która uczciwie komunikuje niepewność. Nie wybaczają AI, która pewnie się myli.

Dowody w agentowym przepływie pracy

Agenci AI potrzebują stanów interfejsu, które dowodzą wykonanej pracy, a nie tylko opisują wysiłek. Dobry agentowy przepływ pracy pokazuje postęp czytelnie dzięki punktom kontrolnym: plan zaakceptowany, źródła zebrane, edycje zastosowane, testy uruchomione, przegląd oczekuje, a wydanie jest zablokowane albo gotowe.

Stan agenta Wzorzec interfejsu Dlaczego ma znaczenie
Planowanie Wyraźny cel i kryteria akceptacji Zapobiega optymalizowaniu aktywności przez agenta zamiast wyniku
Eksploracja Lista źródeł z poziomem pewności i aktualnością Pozwala użytkownikom odróżnić zweryfikowane fakty od roboczych założeń
Wykonanie Podsumowanie zmienionych plików powiązane z punktami kontrolnymi Sprawia, że edycje można przejrzeć bez czytania całego transkryptu
Weryfikacja Test, ścieżka, screenshot albo dowód z działania w runtime Oddziela dowód od syntetycznej pewności
Wydanie Stan zatwierdzenia, deployu albo natywnego przeglądu Nie pozwala, by publikacja ukrywała niedokończoną pracę za zielonymi lokalnymi kontrolami
Antywzorzec: Pojedynczy stan „Gotowe” dla wieloetapowej pracy agenta. Złożona praca potrzebuje widocznego łańcucha odpowiedzialności: co się zmieniło, co to potwierdziło, co odrzucono i co nadal wymaga ludzkiego osądu.

Dieter Rams: dziesięć zasad

„Mniej, ale lepiej”. — Dieter Rams

Dieter Rams to najbardziej wpływowy projektant wzornictwa przemysłowego XX wieku. Jako szef działu projektowania w Braun w latach 1961-1995 tworzył produkty, które po dekadach nadal pozostają ponadczasowe. Jego prace bezpośrednio zainspirowały język projektowy Apple.

Dziesięć zasad dobrego projektowania

1. Dobre projektowanie jest innowacyjne Nie należy kopiować. Warto łączyć rozwijającą się technologię z innowacyjnym projektowaniem.

2. Dobre projektowanie czyni produkt użytecznym Każdy element musi mieć cel. Forma wynika z funkcji.

3. Dobre projektowanie jest estetyczne Piękno nie jest powierzchowne — jest niezbędne. Produkty, których używa się codziennie, wpływają na samopoczucie.

4. Dobre projektowanie czyni produkt zrozumiałym Użytkownicy nie powinni potrzebować instrukcji. Interfejs uczy sam z siebie.

5. Dobre projektowanie jest nienachalne Projektowanie powinno wspierać, a nie przytłaczać. Najważniejsza jest treść użytkownika, nie UI.

/* Obtrusive: UI competes with content */
.editor {
  background: linear-gradient(135deg, purple, blue);
  border: 3px dashed gold;
}

/* Unobtrusive: UI recedes, content shines */
.editor {
  background: var(--color-background);
  border: 1px solid var(--color-border);
}

6. Dobry design jest uczciwy Nie należy stosować dark patterns. Nie należy obiecywać zbyt wiele. O ograniczeniach trzeba mówić jasno.

7. Dobry design jest długowieczny Należy unikać trendów, które szybko się zestarzeją. Klasyka zamiast chwilowej mody.

TRENDY (will date):           TIMELESS:
- Extreme glassmorphism       - Clean typography
- Neon colors, glitch effects - Subtle elevation
- Aggressive gradients        - Neutral palette with considered accent

8. Dobry design jest dopracowany w najdrobniejszym szczególe Nic nie może być przypadkowe. Stany ładowania, stany puste, stany błędów — wszystko zaprojektowane.

9. Dobry design jest przyjazny środowisku Wydajność ma znaczenie środowiskowe. Należy szanować uwagę użytkownika. Efektywny kod.

10. Dobry design to możliwie jak najmniej designu Należy usunąć wszystko, co nie jest konieczne. Najlepszy design jest niewidoczny.


Web patterns 2026

Nowoczesny design webowy wykorzystuje natywne możliwości CSS, które w wielu przypadkach eliminują potrzebę użycia JavaScript. Lata 2025-2026 przyniosły anchor positioning, scroll-driven animations oraz @starting-style do przeglądarek produkcyjnych.

Container queries

Dopasowanie rozmiaru komponentów do ich kontenera, a nie do viewportu.

.card-grid {
  container-type: inline-size;
  container-name: card-grid;
}

.card {
  display: grid;
  gap: 16px;
  padding: 20px;
}

@container card-grid (min-width: 400px) {
  .card {
    grid-template-columns: auto 1fr;
  }
}

@container card-grid (min-width: 600px) {
  .card {
    padding: 32px;
    gap: 24px;
  }
}

Selektor :has()

Wybór elementu nadrzędnego na podstawie elementów potomnych — wcześniej niemożliwy bez JavaScript.

/* Card with image gets different padding */
.card:has(img) {
  padding: 0;
}

.card:has(img) .card-content {
  padding: 20px;
}

/* Form group with error */
.form-group:has(.input:invalid) .form-label {
  color: var(--color-error);
}

/* Highlight navigation when on that page */
.nav-item:has(a[aria-current="page"]) {
  background: var(--color-surface);
}

Zagnieżdżanie CSS

Natywne zagnieżdżanie bez preprocesorów.

.card {
  background: var(--color-surface);
  border-radius: 12px;
  padding: 24px;

  & .card-title {
    font-size: 1.25rem;
    font-weight: 600;
    margin-bottom: 8px;
  }

  & .card-body {
    color: var(--color-text-secondary);
    line-height: 1.6;
  }

  &:hover {
    box-shadow: var(--shadow-md);
  }

  @media (min-width: 768px) {
    padding: 32px;
  }
}

Integracja z HTMX

Interaktywność sterowana przez serwer bez ciężkich frameworków JavaScript.

<!-- Load content on click -->
<button hx-get="/api/more-items"
        hx-target="#item-list"
        hx-swap="beforeend"
        hx-indicator="#loading">
  Load More
</button>

<!-- Form with inline validation -->
<form hx-post="/api/contact"
      hx-target="#form-response"
      hx-swap="outerHTML">
  <input type="email" name="email"
         hx-post="/api/validate-email"
         hx-trigger="blur"
         hx-target="next .error" />
  <span class="error"></span>
</form>

Pozycjonowanie kotwic

Natywne pozycjonowanie CSS jednego elementu względem innego — bez potrzeby używania JavaScript. Dymki, popovery i menu rozwijane, które podążają za swoimi wyzwalaczami.

/* Anchor an element to another */
.trigger {
  anchor-name: --my-trigger;
}

.tooltip {
  position: fixed;
  position-anchor: --my-trigger;
  top: anchor(bottom);
  left: anchor(center);
  translate: -50% 8px;
}

Animacje sterowane przewijaniem

Powiązanie postępu animacji z pozycją przewijania. Wskaźniki postępu czytania, efekty paralaksy i sekwencje ujawniania bez JavaScript.

/* Reading progress bar */
.progress-bar {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 3px;
  background: var(--color-primary);
  transform-origin: left;
  animation: progress linear;
  animation-timeline: scroll();
}

@keyframes progress {
  from { transform: scaleX(0); }
  to { transform: scaleX(1); }
}

@starting-style

Definiowanie stylów początkowych dla elementów dodawanych do DOM — umożliwia animacje wejścia wyłącznie za pomocą CSS, bez JavaScript.

.card {
  opacity: 1;
  transform: translateY(0);
  transition: opacity 0.3s ease, transform 0.3s ease;

  @starting-style {
    opacity: 0;
    transform: translateY(10px);
  }
}

System tokenów projektowych

Kompletny system tokenów zapewniający spójność w całej aplikacji.

:root {
  /* Colors */
  --color-text: #1a1a1a;
  --color-text-secondary: #666666;
  --color-text-muted: #999999;

  --color-background: #ffffff;
  --color-surface: #f8f9fa;
  --color-surface-elevated: #ffffff;

  --color-border: #e5e7eb;
  --color-primary: #3b82f6;
  --color-primary-hover: #2563eb;

  --color-success: #10b981;
  --color-warning: #f59e0b;
  --color-error: #ef4444;

  /* Typography */
  --font-sans: system-ui, -apple-system, sans-serif;
  --font-mono: "SF Mono", Consolas, monospace;

  --text-xs: 0.75rem;
  --text-sm: 0.875rem;
  --text-base: 1rem;
  --text-lg: 1.125rem;
  --text-xl: 1.25rem;
  --text-2xl: 1.5rem;
  --text-3xl: 2rem;

  --leading-tight: 1.25;
  --leading-normal: 1.5;
  --leading-relaxed: 1.75;

  /* Spacing (8px base) */
  --space-1: 0.25rem;   /* 4px */
  --space-2: 0.5rem;    /* 8px */
  --space-3: 0.75rem;   /* 12px */
  --space-4: 1rem;      /* 16px */
  --space-6: 1.5rem;    /* 24px */
  --space-8: 2rem;      /* 32px */
  --space-12: 3rem;     /* 48px */
  --space-16: 4rem;     /* 64px */

  /* Borders */
  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 12px;
  --radius-full: 9999px;

  /* Shadows */
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
  --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.07);
  --shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1);

  /* Transitions */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --duration-fast: 100ms;
  --duration-normal: 200ms;
}

Tryb ciemny zaprojektowany właściwie

Nie wystarczy odwrócić kolorów — należy przeprojektować interfejs z myślą o ciemnym kontekście.

@media (prefers-color-scheme: dark) {
  :root {
    /* Neutrals */
    --color-background: hsl(220, 13%, 10%);
    --color-surface: hsl(220, 13%, 15%);
    --color-surface-elevated: hsl(220, 13%, 18%);
    --color-border: hsl(220, 13%, 23%);

    /* Text (inverted) */
    --color-text: hsl(220, 9%, 93%);
    --color-text-secondary: hsl(220, 9%, 70%);
    --color-text-muted: hsl(220, 9%, 55%);

    /* Adjust saturation for dark mode */
    --color-primary: hsl(220, 80%, 60%);
    --color-success: hsl(142, 70%, 45%);
    --color-error: hsl(0, 80%, 65%);

    /* Shadows in dark mode need adjustment */
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
    --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.4);
  }
}

Zasady trybu ciemnego: - Zmniejszyć nasycenie na dużych powierzchniach - Zwiększyć jasność kolorów akcentowych - Wzmocnić cienie (potrzebują większego kontrastu) - Projektować tryb ciemny celowo, a nie traktować go jako późniejszy dodatek


Przepływy pracy przy ekstrakcji z Figma

Przekształcanie plików projektowych w kod produkcyjny wymaga systematycznej ekstrakcji tokenów projektowych (design tokens) — kolorów, typografii, odstępów i efektów, które definiują język projektowy.

Eksport Figma Variables

Natywna funkcja Variables w Figma zapewnia najczystszą ścieżkę ekstrakcji:

Kroki eksportu: 1. Otworzyć plik Figma → panel Local Variables 2. Kliknąć menu kolekcji → „Export to JSON” 3. Zapisać jako figma-variables.json

Struktura tokenów JSON:

{
  "colors": {
    "primitive": {
      "blue-500": { "value": "#3b82f6", "type": "color" },
      "blue-600": { "value": "#2563eb", "type": "color" }
    },
    "semantic": {
      "primary": { "value": "{colors.primitive.blue-500}", "type": "color" },
      "primary-hover": { "value": "{colors.primitive.blue-600}", "type": "color" }
    }
  },
  "spacing": {
    "1": { "value": "4px", "type": "spacing" },
    "2": { "value": "8px", "type": "spacing" },
    "4": { "value": "16px", "type": "spacing" }
  }
}

Transformacja tokenów do CSS

Właściwości niestandardowe CSS:

:root {
  /* Primitive colors (direct values) */
  --color-blue-50: #eff6ff;
  --color-blue-100: #dbeafe;
  --color-blue-500: #3b82f6;
  --color-blue-600: #2563eb;
  --color-blue-900: #1e3a8a;

  /* Semantic colors (reference primitives) */
  --color-primary: var(--color-blue-500);
  --color-primary-hover: var(--color-blue-600);
  --color-background: var(--color-white);
  --color-surface: var(--color-gray-50);

  /* Spacing (8px grid) */
  --space-1: 0.25rem;  /* 4px */
  --space-2: 0.5rem;   /* 8px */
  --space-4: 1rem;     /* 16px */
  --space-6: 1.5rem;   /* 24px */
  --space-8: 2rem;     /* 32px */

  /* Typography */
  --font-size-sm: 0.875rem;
  --font-size-base: 1rem;
  --font-size-lg: 1.125rem;
  --line-height-tight: 1.25;
  --line-height-normal: 1.5;

  /* Effects */
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
  --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.07);
  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 12px;
}

Tokeny trybu ciemnego:

@media (prefers-color-scheme: dark) {
  :root {
    --color-background: var(--color-gray-900);
    --color-surface: var(--color-gray-800);
    --color-text: var(--color-gray-100);
    --color-text-secondary: var(--color-gray-400);

    /* Adjusted shadows for dark mode */
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
    --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.4);
  }
}

Transformacja tokenów na SwiftUI

Rozszerzenie Color:

import SwiftUI

extension Color {
    // MARK: - Primitive Colors
    static let blue50 = Color(hex: "eff6ff")
    static let blue500 = Color(hex: "3b82f6")
    static let blue600 = Color(hex: "2563eb")

    // MARK: - Semantic Colors
    static let brandPrimary = Color.blue500
    static let brandPrimaryHover = Color.blue600

    // MARK: - Surface Colors
    static let surfaceBackground = Color(light: .white, dark: Color(hex: "0f172a"))
    static let surfaceElevated = Color(light: Color(hex: "f8fafc"), dark: Color(hex: "1e293b"))
}

extension Color {
    init(hex: String) {
        // Standard hex parsing implementation
    }

    init(light: Color, dark: Color) {
        self.init(UIColor { traits in
            traits.userInterfaceStyle == .dark ? UIColor(dark) : UIColor(light)
        })
    }
}

Stałe odstępów:

enum Spacing {
    static let xs: CGFloat = 4    // --space-1
    static let sm: CGFloat = 8    // --space-2
    static let md: CGFloat = 16   // --space-4
    static let lg: CGFloat = 24   // --space-6
    static let xl: CGFloat = 32   // --space-8
}

// Usage
VStack(spacing: Spacing.md) {
    // ...
}
.padding(Spacing.lg)

Lista kontrolna przekazania projektu przez projektanta

Co projektanci powinni wyeksportować:

Typ zasobu Format Uwagi
Kolory Zmienne JSON Uwzględnić tryb jasny i ciemny
Typografia Eksport stylów Krój pisma, rozmiar, grubość, line-height
Odstępy Zmienne JSON Udokumentowana jednostka bazowa
Ikony SVG Konturowe, jednokolorowe
Obrazy PNG @2x/@3x lub WebP Z kompresją
Komponenty Linki Figma Jako odniesienie podczas implementacji
Kryteria bramki jakości:
  • [ ] Wszystkie kolory zdefiniowane jako zmienne (bez hardcodowanych wartości hex)
  • [ ] Typografia używa zdefiniowanych stylów tekstu
  • [ ] Odstępy są zgodne z systemem siatki (baza 8px)
  • [ ] Dostarczono warianty dark mode
  • [ ] Udokumentowano stany interaktywne (hover, active, disabled)
  • [ ] Oznaczono responsywne punkty przełamania
  • [ ] Odnotowano wymagania dotyczące dostępności (współczynniki kontrastu)

Co otrzymuje developer:

  1. Pliki tokenów (JSON/CSS/Swift, zależnie od platformy)
  2. Specyfikacje komponentów z wymiarami
  3. Eksporty zasobów w wymaganych formatach
  4. Dokumentację interakcji (stany, animacje)
  5. Adnotacje dotyczące dostępności

Tabele szybkiego odniesienia

Zasady Gestalt

Zasada Reguła Zastosowanie
Bliskość Powiązane = blisko Formularze, sekcje
Podobieństwo Ten sam wygląd = ta sama funkcja Przyciski, karty
Figura-tło Wyraźne oddzielenie warstw Okna modalne, karty
Ciągłość Podążanie wzdłuż linii Osie czasu, wyrównanie
Domknięcie Mózg domyka kształty Ikony, wskazówki przewijania
### Typografia
Element Rozmiar Grubość
--------- ------ --------
Tekst główny 16px 400
Nagłówki 24-48px 600-700
Etykiety UI 12-14px 500
Podpisy 12px 400
### Role kolorów
Rola Tryb jasny Tryb ciemny
------ ------------ -----------
Tło #ffffff #0f172a
Powierzchnia #f4f5f7 #1e293b
Obramowanie #e4e6ea #334155
Tekst #1a1a2e #f1f5f9
Tekst przygaszony #6b7280 #94a3b8
Główny #3b82f6 #60a5fa
Sukces #22c55e #4ade80
Błąd #ef4444 #f87171
### Skala odstępów
Token Wartość Zastosowanie
------- ------- -----
–space-1 4px Odstępy między ikonami
–space-2 8px Elementy inline
–space-4 16px Domyślne odstępy
–space-6 24px Padding kart
–space-8 32px Odstępy między sekcjami
–space-16 64px Sekcje strony

Lista kontrolna designu

Przed wdrożeniem dowolnego interfejsu należy zweryfikować:

Gestalt

  • [ ] Powiązane elementy znajdują się bliżej siebie niż elementy niepowiązane (bliskość)
  • [ ] Podobne funkcje mają podobną stylistykę (podobieństwo)
  • [ ] Pierwszy plan jest wyraźnie oddzielony od tła (figura-tło)
  • [ ] Wzrok naturalnie podąża przez układ (ciągłość)

Typografia

  • [ ] Podstawowy rozmiar fontu wynosi co najmniej 16px
  • [ ] Wysokość linii dla tekstu głównego wynosi 1.5+
  • [ ] Długość wiersza nie przekracza 75 znaków
  • [ ] Hierarchia jest wyraźna (można rozróżnić 3 poziomy)
  • [ ] W całym interfejsie użyto spójnej skali

Kolor

  • [ ] Cały tekst spełnia kontrast 4.5:1 (WCAG AA)
  • [ ] Kolor nie jest jedynym wskaźnikiem (są też ikony/etykiety)
  • [ ] Tryb ciemny zaprojektowano świadomie
  • [ ] Zachowano proporcję 60-30-10

Hierarchia wizualna

  • [ ] Można wskazać najważniejszy element nr 1
  • [ ] Wzrok podąża w zamierzonej kolejności
  • [ ] W każdej sekcji znajduje się jeden wyraźny CTA
  • [ ] Skala pisma jest spójna

Odstępy

  • [ ] Wszystkie odstępy korzystają ze zdefiniowanej skali (bez magicznych liczb)
  • [ ] Karty/komponenty mają spójny padding
  • [ ] Odstępy na urządzeniach mobilnych są komfortowe
  • [ ] Wyrównanie siatki jest spójne (baza 8px)

Interakcja

  • [ ] Czy użytkownicy mogą osiągać cele bez myślenia o narzędziu?
  • [ ] Czy UI dostosowuje się do bieżącego kontekstu?
  • [ ] Czy narzędzia są widoczne tylko wtedy, gdy są potrzebne?
  • [ ] Czy wielokrotne używanie uczy szybszych metod?

Interfejsy AI

  • [ ] Każde twierdzenie faktograficzne ma możliwe do prześledzenia źródło
  • [ ] Przesyłanie strumieniowe pokazuje etapy procesu, a nie tylko spinner
  • [ ] Stany błędów są przejrzyste, nie ukryte
  • [ ] Wyniki o niskiej pewności są wizualnie odróżnione

Kontrola według Dieter Ramsa

  • [ ] Czy można coś usunąć?
  • [ ] Czy każdy element służy funkcji?
  • [ ] Czy za 5 lat nadal nie będzie to wyglądać przestarzale?
  • [ ] Czy zaprojektowano każdy stan?

Zasoby

Książki: - As Little Design as Possible by Sophie Lovell (Dieter Rams) - The Elements of Typographic Style by Robert Bringhurst

Narzędzia: - WebAIM Contrast Checker - Type Scale Generator - Figma Tokens Studio — zarządzanie design tokens

Systemy projektowe: - Apple HIG - Material Design 3 - Radix UI - shadcn/ui

Studia przypadków designu

Dogłębne analizy 48 wyjątkowych produktów, dokumentujące wzorce i zasady warte zapożyczenia.

Narzędzia deweloperskie i AI

Produkt Kluczowy wkład
Figma Obecność wielu osób w czasie rzeczywistym, panele świadome kontekstu
Warp Terminal oparty na blokach, pomost CLI-GUI
Framer Wizualny responsywny design, kontrolki właściwości
Vercel Doskonałość dark mode, ambient status
Linear Optimistic UI, przepływ pracy nastawiony na klawiaturę
Raycast System rozszerzeń, szybkie akcje
Stripe Doskonała dokumentacja, design API
Perplexity AI stawiające cytowania na pierwszym planie, fazy strumieniowania
Obsidian Kompozycyjność local-first, interfejsy grafów wiedzy
### Apple-native i narzędzia kreatywne
Produkt Kluczowy wkład
--------- ------------------
Flighty 15 inteligentnych stanów, Live Activities, wizualizacja danych
Halide Inteligentna aktywacja, sterowanie gestami
Bear Typografia na pierwszym planie, tagowanie w tekście
Craft Podejście native-first między platformami, zagnieżdżone strony
Things Odroczone terminy, wzorce szybkiego wprowadzania
Darkroom Immersyjny ciemny UI, edycja skoncentrowana na zdjęciach
Procreate Narzędzia kreatywne oparte przede wszystkim na gestach
Overcast Niewidoczna inżynieria audio jako projektowanie interfejsu
Camo Profesjonalny UI do produkcji wideo
Ivory Dopracowanie osi czasu, swobodna precyzja
Anybox Przejrzystość zgodna z natywnymi wzorcami platformy
Drafts Klarowność przechwytywania z tekstem na pierwszym planie
Notion Calendar Precyzja kalendarza, integracja z przestrzenią roboczą
### Produktywność, wiedza i finanse
Produkt Kluczowy wkład
--------- ------------------
Superhuman Reguła 100 ms, trening palety poleceń, onboarding przez praktykę
Notion System bloków, polecenia ukośnikiem
Arc Spaces, widok dzielony, pasek poleceń
Todoist Ciepły minimalizm, maksymalna powściągliwość
Amie Radosna produktywność, ciepły minimalizm
Loom Przyjazny profesjonalizm asynchronicznego wideo
Pitch Odważny język projektowania prezentacji
Readwise Reader Narzędzia do głębokiej lektury, kosmiczny branding
Copilot Money Filmowa wizualizacja danych finansowych
1Password Bezpieczeństwo bez zbędnych przeszkód
Mercury Filmowa elegancja bankowości
### Konsumenckie, społecznościowe i zaufanie
Produkt Kluczowy wkład
--------- ------------------
Spotify Kolor, emocje i skala
Duolingo Grywalizacja jako język projektowania
Signal Bezpieczeństwo przez prostotę
Airbnb Zaufanie w skali marketplace
Bluesky Przejrzystość algorytmiczna
Letterboxd Kino jako obiekt społeczny
Strava Dane GPS jako waluta społeczna
Apple Music Głos redakcyjny, dźwięk przestrzenny
Headspace Spokój jako strategia interfejsu
Zomato UX jedzenia oparty na osobowości
### Fizyczne produkty, gry i dostępność
Produkt Kluczowy wkład
--------- ------------------
Balatro Pętle sprzężenia zwrotnego, systemy game-feel
Rivian Fotografia przygodowa i monumentalna typografia
Teenage Engineering Ograniczenia jako tożsamość estetyczna
OKO Dostępność audio-haptyczna
CARROT Weather Osobowość jako wyróżnik aplikacji narzędziowej

Ten przewodnik rozwija się dzięki praktyce. Zasady projektowania są ponadczasowe, ale ich zastosowanie ewoluuje wraz z technologią i zrozumieniem.