Używamy cookies, żeby zwiększyć Twoje doświadczenia na stronie
CodeWorlds

Design Tokens i Systematyczny CSS - Kosmiczny Kod Designu

Pilotze, wyobraz sobie, ze kazdy statek w flocie galaktycznej uzywa dokladnie tych samych kolorow statusu, tych samych odstepow miedzy panelami i tej samej typografii na monitorach. To nie przypadek -- to design system. W swiecie frontendu odpowiednikiem sa design tokens -- centralne zrodlo prawdy dla wszystkich wartosci wizualnych w aplikacji.

Czym sa Design Tokens?

Design tokens to nazwane wartosci reprezentujace decyzje designowe: kolory, odstepy, rozmiary czcionek, cienie, promienie zaokraglen. Zamiast rozrzucac magiczne liczby po kodzie, definiujesz je w jednym miejscu:

1// tokens.js -- centralne zrodlo prawdy
2const tokens = {
3  colors: {
4    primary: '#7c4dff',
5    primaryLight: '#b388ff',
6    primaryDark: '#651fff',
7    success: '#00e676',
8    warning: '#ffa726',
9    danger: '#f44336',
10    bgDark: '#0a0a2e',
11    bgSurface: '#1a1a4e',
12    textPrimary: '#e0e0e0',
13    textMuted: '#9e9e9e',
14    border: '#3949ab',
15  },
16  spacing: {
17    xs: '4px',
18    sm: '8px',
19    md: '16px',
20    lg: '24px',
21    xl: '32px',
22    xxl: '48px',
23  },
24  fontSize: {
25    xs: '12px',
26    sm: '14px',
27    md: '16px',
28    lg: '20px',
29    xl: '28px',
30    xxl: '36px',
31  },
32  borderRadius: {
33    sm: '4px',
34    md: '8px',
35    lg: '12px',
36    xl: '20px',
37    full: '9999px',
38  },
39  shadows: {
40    sm: '0 2px 4px rgba(0,0,0,0.1)',
41    md: '0 4px 12px rgba(0,0,0,0.2)',
42    lg: '0 8px 24px rgba(0,0,0,0.3)',
43    glow: '0 0 20px rgba(124,77,255,0.3)',
44  },
45};

Uzywanie tokenow w komponentach

Gdy masz zdefiniowane tokeny, uzywasz ich zamiast bezposrednich wartosci:

1import { tokens } from './tokens';
2
3// W inline styles
4function Card({ children }) {
5  return (
6    <div style={{
7      background: tokens.colors.bgSurface,
8      padding: tokens.spacing.lg,
9      borderRadius: tokens.borderRadius.lg,
10      border: `1px solid ${tokens.colors.border}`,
11    }}>
12      {children}
13    </div>
14  );
15}
1// W styled-components
2const Card = styled.div`
3  background: ${tokens.colors.bgSurface};
4  padding: ${tokens.spacing.lg};
5  border-radius: ${tokens.borderRadius.lg};
6  border: 1px solid ${tokens.colors.border};
7`;

Tokeny jako CSS Variables

Najlepszy sposob to polaczenie tokenow JavaScript z CSS Variables -- definiujesz tokeny w JS (latwe do zarzadzania), a przekazujesz do CSS jako zmienne (wydajne renderowanie):

1function applyTokens(tokens) {
2  const vars = {};
3  vars['--color-primary'] = tokens.colors.primary;
4  vars['--color-bg'] = tokens.colors.bgDark;
5  vars['--color-surface'] = tokens.colors.bgSurface;
6  vars['--color-text'] = tokens.colors.textPrimary;
7  vars['--spacing-md'] = tokens.spacing.md;
8  vars['--spacing-lg'] = tokens.spacing.lg;
9  vars['--radius-lg'] = tokens.borderRadius.lg;
10  return vars;
11}
12
13function App() {
14  return (
15    <div style={applyTokens(tokens)} className="app">
16      {/* CSS uzywa var(--color-primary) itd. */}
17    </div>
18  );
19}

Spójny system kolorow

Dobry system kolorow ma strukture:

1const colorSystem = {
2  // Kolory bazowe
3  blue: { 50: '#e3f2fd', 100: '#bbdefb', 500: '#2196f3', 900: '#0d47a1' },
4  purple: { 50: '#f3e5f5', 100: '#e1bee7', 500: '#9c27b0', 900: '#4a148c' },
5
6  // Kolory semantyczne (uzywane w kodzie)
7  primary: 'var(--blue-500)',
8  success: 'var(--green-500)',
9  warning: 'var(--orange-500)',
10  danger: 'var(--red-500)',
11
12  // Kolory powierzchni
13  background: '#0a0a2e',
14  surface: '#1a1a4e',
15  surfaceHover: '#2a2a5e',
16};

Kolory semantyczne (primary, success, danger) oddzielasz od kolorow bazowych (blue-500, red-400). Dzieki temu zmiana motywu to zmiana mapowania, nie szukanie po calym kodzie.

System spacingu

Spacing (odstepy) oparty na skali -- kazda nastepna wartosc jest wielokrotnoscia bazowej:

1// Skala 4px (Tailwind-style)
2const spacing = {
3  0: '0px',
4  1: '4px',
5  2: '8px',
6  3: '12px',
7  4: '16px',
8  5: '20px',
9  6: '24px',
10  8: '32px',
11  10: '40px',
12  12: '48px',
13  16: '64px',
14};

Uzywanie skali zamiast dowolnych wartosci gwarantuje wizualna spojnosc -- elementy na ekranie sa rownomiernie rozmieszczone, co daje profesjonalny wyglad.

Typografia jako system

1const typography = {
2  fontFamily: {
3    sans: "'Inter', 'Segoe UI', sans-serif",
4    mono: "'Fira Code', monospace",
5  },
6  fontSize: {
7    xs: ['12px', { lineHeight: '16px' }],
8    sm: ['14px', { lineHeight: '20px' }],
9    base: ['16px', { lineHeight: '24px' }],
10    lg: ['20px', { lineHeight: '28px' }],
11    xl: ['28px', { lineHeight: '36px' }],
12    '2xl': ['36px', { lineHeight: '44px' }],
13  },
14  fontWeight: {
15    normal: 400,
16    medium: 500,
17    semibold: 600,
18    bold: 700,
19  },
20};

Kazdy rozmiar czcionki ma przyporzadkowana wysokosc linii -- to eliminuje chaos typograficzny.

Token Composition -- skladanie tokenow

Zaawansowany wzorzec to skladanie tokenow -- tworzenie bardziej szczegolowych tokenow z bazowych:

1// Tokeny bazowe (primitive)
2const primitives = {
3  blue500: '#7c4dff',
4  blue300: '#b388ff',
5  green500: '#00e676',
6  red500: '#f44336',
7  gray900: '#0a0a2e',
8  gray800: '#1a1a4e',
9  gray100: '#e0e0e0',
10  gray400: '#9e9e9e',
11};
12
13// Tokeny semantyczne (zlozone z bazowych)
14const semantic = {
15  colorPrimary: primitives.blue500,
16  colorPrimaryLight: primitives.blue300,
17  colorSuccess: primitives.green500,
18  colorDanger: primitives.red500,
19  colorBackground: primitives.gray900,
20  colorSurface: primitives.gray800,
21  colorText: primitives.gray100,
22  colorTextMuted: primitives.gray400,
23};
24
25// Tokeny komponentowe (zlozone z semantycznych)
26const components = {
27  buttonPrimaryBg: semantic.colorPrimary,
28  buttonPrimaryText: '#ffffff',
29  buttonDangerBg: semantic.colorDanger,
30  cardBg: semantic.colorSurface,
31  cardBorder: primitives.blue500 + '40',
32};

Trzy warstwy: bazowe (wartosci) -> semantyczne (znaczenie) -> komponentowe (uzycie). Zmiana jednego bazowego tokenu kaskadowo aktualizuje wszystko.

Style Dictionary -- automatyzacja tokenow

W duzych projektach tokeny przechowuje sie w formacie JSON i automatycznie generuje pliki dla roznych platform za pomoca narzedzia Style Dictionary:

1{
2  "color": {
3    "primary": { "value": "#7c4dff" },
4    "success": { "value": "#00e676" },
5    "background": { "value": "#0a0a2e" }
6  },
7  "spacing": {
8    "sm": { "value": "8px" },
9    "md": { "value": "16px" },
10    "lg": { "value": "24px" }
11  }
12}

Style Dictionary generuje z tego:

  • CSS Variables -- dla aplikacji webowych
  • JavaScript/TypeScript -- dla React
  • Swift/Kotlin -- dla aplikacji mobilnych

Jedno zrodlo prawdy, wiele formatow wyjsciowych.

Automatyzacja spojnosci

Tworzenie komponentu

TokenPreview
pomaga kontrolowac caly system:

1function TokenPreview({ tokens }) {
2  return (
3    <div>
4      <h2>Kolory</h2>
5      {Object.entries(tokens.colors).map(([name, value]) => (
6        <div key={name} style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
7          <div style={{ width: 40, height: 40, background: value, borderRadius: 8 }} />
8          <span>{name}: {value}</span>
9        </div>
10      ))}
11
12      <h2>Spacing</h2>
13      {Object.entries(tokens.spacing).map(([name, value]) => (
14        <div key={name} style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
15          <div style={{ width: value, height: 16, background: '#7c4dff' }} />
16          <span>{name}: {value}</span>
17        </div>
18      ))}
19    </div>
20  );
21}

Kiedy uzywac design tokens?

  • Kazdy projekt wiekszy niz landing page -- tokeny oszczedzaja czas w dluzszej perspektywie
  • Praca zespolowa -- kazdy developer uzywa tych samych wartosci
  • Wiele motywow -- zmiana jednego obiektu zmienia caly wyglad
  • Spojnosc miedzy platformami -- Style Dictionary generuje tokeny dla React, React Native, iOS, Android
  • Skladanie tokenow -- trzy warstwy (bazowe -> semantyczne -> komponentowe) daja pelna kontrole
Przejdź do CodeWorlds