Перейти к основному содержимому

Дизайн-токены

Дизайн-токены — атомарные переменные, которые хранят значения UI-параметров: цвета, типографику, отступы, радиусы, тени. Токены живут отдельно от компонентов и применяются везде, где нужна визуальная консистентность.

Преимущества:

  • Консистентность — единый источник значений для всей команды
  • Темизация — простая смена тем через изменение токенов
  • Платформенная независимость — токены для web, iOS, Android
  • Ребрендинг — изменения без массовой миграции кода

Структура токенов

Токены организованы в три уровня иерархии:

1. Core tokens (базовые)

"Базовые" значения: палитра, базовые размеры, исходные числовые значения.

// tokens/base.json
{
"color": {
"base": {
"neutral": {
"900": { "value": "#1b1b1b" },
"50": { "value": "#f5f5f5" }
},
"blue": {
"500": { "value": "#3b82f6" }
}
}
},
"space": {
"base": {
"4": { "value": "16px" },
"6": { "value": "24px" }
}
}
}

2. Semantic tokens (семантические)

Значения с бизнес-смыслом, которые ссылаются на core токены.

// tokens/semantic.json
{
"color": {
"text": {
"primary": { "value": "{color.base.neutral.900}" },
"inverse": { "value": "{color.base.neutral.50}" }
},
"bg": {
"surface": { "value": "{color.base.neutral.50}" },
"brand": { "value": "{color.base.blue.500}" }
}
},
"space": {
"m": { "value": "{space.base.4}" },
"l": { "value": "{space.base.6}" }
}
}

3. Component tokens (компонентные)

Локальные токены для специфичных компонентов. Используются только когда компонент требует уникальные значения, не покрытые семантическими токенами.

// tokens/components.json
{
"button": {
"primary": {
"bg": { "value": "{color.bg.brand}" },
"text": { "value": "{color.text.inverse}" }
}
}
}

MUST

  1. Все UI-значения берутся из токенов:

    • Цвета, типографика, отступы, размеры, радиусы, тени
  2. UI-код использует только семантические или компонентные токены:

    • Core токены используются только внутри слоя токенов
    • Запрещено использовать core токены напрямую в UI-коде
  3. Новые компоненты не добавляют захардкоженных значений:

    • ❌ Запрещено: color: '#1b1b1b', padding: 16px
    • ✅ Правильно: color: var(--color-text-primary), padding: var(--space-m)
  4. Имена токенов отражают смысл использования, а не конкретное значение:

    • ✅ Правильно: color.text.primary, color.bg.surface, space.m
    • ❌ Неправильно: color.blue.500, space.cardPadding, color.darkGray
  5. Иерархия должна быть предсказуемой и единообразной:

   color.text.primary
color.text.secondary
color.bg.surface
color.bg.brand
space.s
space.m
space.l
radius.s
radius.m
shadow.level.1
shadow.level.2

SHOULD

  1. Семантика важнее конкретного значения:

    • color.text.primary вместо color.neutral.900
    • space.m вместо space.16px
  2. Компонентные токены создавать только для уникальных компонентов:

    • Не создавать компонентные токены для каждого компонента без необходимости
    • Использовать семантические токены везде, где возможно

FORBIDDEN

  1. Использовать core токены напрямую в UI:
/* ❌ Неправильно */
.title {
color: var(--color-base-neutral-900);
}

/* ✅ Правильно */
.title {
color: var(--color-text-primary);
}
  1. Создавать токены "на один экран" или с привязкой к контексту:
   /* ❌ Неправильно */
{
"space": {
"promoCardSpecial": { "value": "18px" },
"landingHeroPadding": { "value": "32px" }
}
}

/* ✅ Правильно */
{
"space": {
"l": { "value": "18px" },
"xl": { "value": "32px" }
}
}
  1. Смешивать захардкоженные значения с токенами:
/* ❌ Неправильно — часть значений из токенов, часть захардкожена */
.card {
color: var(--color-text-primary);
background: #ffffff; /* захардкожено */
padding: var(--space-m);
border-radius: 8px; /* захардкожено */
}

Темизация и ребрендинг

MUST

Переключение темы меняет семантические токены, а не UI-код:

/* ✅ Правильно */
:root {
--color-text-primary: #1b1b1b;
--color-bg-surface: #ffffff;
}

[data-theme='dark'] {
--color-text-primary: #f5f5f5;
--color-bg-surface: #121212;
}

.card {
color: var(--color-text-primary);
background: var(--color-bg-surface);
}

Поставка токенов

MUST

  1. Токены хранятся отдельно от продуктового кода:

    • Отдельный репозиторий или workspace-пакет
    • Независимая версионность
  2. Продукты получают токены как артефакты сборки:

    • CSS variables для web
    • TypeScript/JavaScript для типизации
    • JSON для других платформ (iOS, Android)

SHOULD

  1. Использовать генераторы токенов:

  2. Версионировать токены:

    • Semantic versioning (semver)
    • Changelog для изменений
    • Миграционные гайды при breaking changes

Примеры использования

✅ Правильно

/* CSS */
.card {
background: var(--color-bg-surface);
color: var(--color-text-primary);
padding: var(--space-m);
border-radius: var(--radius-m);
box-shadow: var(--shadow-level-1);
}
/* Tailwind CSS */
<div className="text-text-primary bg-bg-surface p-m rounded-m shadow-1">
Контент карточки
</div>

/* MUI System */
<Box
sx={{
color: 'text.primary',
bgcolor: 'bg.surface',
p: 'm',
borderRadius: 'm',
boxShadow: 1,
}}
>
Контент карточки
</Box>

❌ Неправильно

/* ❌ Захардкоженные значения */
.card {
background: #fff;
color: #1b1b1b;
padding: 16px;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
/* ❌ Захардкоженные значения в Tailwind */
<div className="text-[#1b1b1b] bg-white p-4 rounded-xl">
Контент карточки
</div>

/* ❌ Использование core токенов напрямую */
<Box
sx={{
color: 'base.neutral.900',
bgcolor: 'base.neutral.50',
}}
>
Контент карточки
</Box>

Добавление нового токена