Дизайн-токены — это язык, понятный как дизайнерам, так и разработчикам. Без него продукт получается разрозненным и неповоротливым. Токены и правильный нейминг помогают создавать новые разделы быстрее, а дизайнерам больше думать о сценариях и создавать визуал в рамках продукта.

Если в вашем коде и макетах до сих пор живут значения типа #0055FF — вы копите технический долг, ведь если понадобится изменить этот цвет на другой, придется менять и все компоненты, где используется это значение. А про разные темы вообще можете забыть...

Грамотно спроектированная система токенов автоматически исключает все ошибки и позволяет максимально гибко кастомизировать и расширять дизайн продукта в сжатые сроки.

В конце статьи будут ссылки на доп. материалы из реальных дизайн-систем, откуда я брал информацию.

Архитектура токенов: 3 уровня абстракции

Мы будем использовать самую популярную трехслойную модель (Примитив → Семантика → Компонент). Она сейчас используется в самых передовых дизайн-системах. Для большей ясности я добавил еще и нулевой слой — сырые данные.

структура токенов цвета фона в accent default кнопке
структура токенов цвета фона в accent default кнопке

0. Raw Values (Сырые значения) — #0055FF. Это сырой код цвета, размера, отступа и т.п.

1. Primitive tokens (Базовые значения или ресурсы): служат для того, чтобы оцифровать сырые данные, от которых наследуются все остальные уровни. Если бренд решит, что «фирменный синий» должен стать чуть светлее, вы поменяете HEX-код только в одном примитиве blue-500. Это изменение автоматически обновится во всех семантических токенах (bg-primarytext-link), и вам не придется переименовывать их или искать по всему коду.

2. Semantic tokens (Семантические): описывают роль или предназначение ресурса в интерфейсе. Например: color-bg-primary-hover, в основе которого лежит примитивный токен blue-600. Именно на этом слое мы внедряем темы: один и тот же семантический токен в светлой теме ссылается на светлый примитив, а в темной — на темный.

3. Component tokens (Компонентные): описывают конкретное место применения стиля внутри отдельного элемента. Например: color-button-bg-primary-hover. Они позволяют точечно настраивать стиль конкретного компонента, не затрагивая остальные элементы, которые могут использовать тот же семантический токен. Если вам нужно изменить цвет фона только у главной кнопки, вы меняете значение в компоненте button.

Семантические токены vs Компонентные

У вас, скорее всего, возникает резонный вопрос: как это все использовать? Семантические токены, компонентные. Это должно быть одновременно или можно по-отдельности?

Зачастую семантические токены используются сразу в нескольких компонентах, чтобы не плодить лишний код. Но если один элемент должен вести себя иначе — мы внедряем компонентный токен. Это позволяет менять стиль конкретной кнопки, не ломая остальные элементы системы, которые используют те же цвета. По сути, компонентные токены — это управляемые исключения.

Семантика отвечает на вопрос «Зачем?», в то время как Компонентные токены на вопрос «Где?».

Формула нейминга у них схожая:

Семантика — [категория]-[свойство]-[роль]-[яркость]-[состояние]
Компонент — [категория]-[компонент]-[свойство]-[роль]-[яркость]-[состояние]

Как вы можете видеть, на компонентном слое в цепочке просто добавляется [компонент].

Дальше мы рассмотрим все эти категории / свойства / роли и т.д. более подробно, и тогда вам станет понятно, о чем идет речь.

Главное запомните золотое правило: если токен переиспользуется в разных местах — это Semantic token. Если нужно изменить цвет ховера только у одной кнопки — это Component token.

Разделы нейминга токенов

  1. Category (Главная папка)color (цвета)spacing (отступы)radius (скругления)shadow (тени)typography (шрифты)size (ширина/высота)z-index (слои)opacity (прозрачность)duration (анимация)

  2. Property (Свойство: к чему относится)bg / surface (фон)text (текст)border (рамка)icon (иконка)outline / ring (фокус)overlay (подложка под модалкой)

  3. Role (Смысл / Роль)primary / secondary / tertiary (важность)brand / accent (фирменный стиль)success (успех/зеленый)warning (предупреждение/желтый)danger / error (ошибка/красный)neutral (нейтральный/серый)inverse (для темных фонов)static (не меняется в темах: white/black)

  4. Prominence (Иерархия / Яркость)default / main / base — точка отсчета.muted (приглушенный)subtle (едва заметный)intense (усиленный)on-brand (контрастный контент поверх брендового фона)

  5. State / Modifier / Size (Состояние)Состояния: hover, active, focus, disabled.Размеры: sm, md, lg, xl.

Важное правило состояния default:

Состояние default писать не обязательно. Токен color-text-primary по умолчанию находится в default-состоянии. Другие же состояния мы добавляем после -primary, например, color-text-primary-hover

Примеры построения структуры токенов

Далее потренируемся на конкретных примерах, чтобы на практике раз и навсегда разобраться в нейминге токенов.

Кнопка accent в default-состоянии и ее структура токенов
Кнопка accent в default-состоянии и ее структура токенов

В примере выше наглядно показана структура нейминга. В основе лежит сырое значение, после чего семантика усложняется и становится более конкретной и уточняющей. Заметьте, я не пишу -default в конце, потому что и так понятно, что это спокойное состояние!

Кнопка accent в состоянии hover и ее структура токенов
Кнопка accent в состоянии hover и ее структура токенов

А вот так выглядит нейминг кнопки в hover-состоянии. Т.е. каждый уровень абстракции делает нашу дизайн-систему более гибкой, но при этом наследует базовую палитру. С помощью компонентного слоя мы можем кастомизировать кнопку отдельно от всех остальных элементов, не мешая им.

В этом примере я уже пишу флаг -hover в конце, чтобы связать состояние «при наведении».

Кнопка secondary в default-состоянии и ее структура токенов
Кнопка secondary в default-состоянии и ее структура токенов

То же самое и с secondary button, в которой используется уже палитра с прозрачностью! Мы можем просто переключить палитру и получить совершенно другую кнопку — в этом сила токенов!

Текст кнопки secondary в default-состоянии и ее структура токенов
Текст кнопки secondary в default-состоянии и ее структура токенов

Далее рассмотрим, как задаются токены для текста внутри secondary кнопки. Это не сложно — мы должны только лишь добавить тип text после основной категории или названия компонента — и будет токен для текста!

Обратите внимание, что на втором слое у нас появился модификатор on-, который обозначает, что данный токен предназначается для того элемента, который будет поверх secondary слоя. Пишется он только в семантическом слое, чтобы не путать разработчиков.

Текст кнопки secondary в hover-состоянии и ее структура токенов
Текст кнопки secondary в hover-состоянии и ее структура токенов

А вот и hover-состояние подъехало — в кноце просто добавляем .hover

Как вы можете видеть, сначала всегда идет категория: colorspacingtypography и т.п., чтобы разработчикам было проще искать нужный токен в коде, затем идет компонент или свойство, за которыми уже следуют модификаторы.

Это не сложнее, чем собирать билд в онлан-игре! Всего-то нужно запомнить 3 слоя и соблюдать принцип «от общего к частному» — от категории к модификаторам и состояниям.

Скругление элемента switch в токенах
Скругление элемента switch в токенах

С некоторыми токенами все гораздо проще — достаточно выстроить грамотную иерархию, а над состояниями можно не париться!

Вы можете спросить, зачем здесь 4 слоя? Можно же просто сразу указать, что 999px — это radius.max, и зачастую так и делают, просто доп. уровень помогает нам привязать значения к пиксельной сетке и более гибко настраивать разные свойства, потому что border radius и gap могут жить по своим законам внутри одной дизайн-системы.

Как работать с темной темой

Чтобы дизайн легко адаптировался под разные темы, а нейминг не путал разработчиков, мы с вами составляли 3 слоя токенов. Вот как выглядит светлая и темная тема в коде:

/* 1. БАЗОВЫЙ УРОВЕНЬ (Primitive Tokens) */
/* Создаем неизменную палитру. Эти токены вообще ничего не знают про темы. */
:root {
  --color-white: #ffffff;
  --color-gray-900: #121212;
  --color-blue-500: #335CFF;
  --color-blue-400: #5C7CFF; /* Чуть светлее для темной тем�� */

  /* 2. СЕМАНТИЧЕСКИЙ УРОВЕНЬ: СВЕТЛАЯ ТЕМА (По умолчанию) */
  /* Раздаем логические роли, ссылаясь на базовую палитру */
  --color-bg-primary: var(--color-white);
  --color-text-main: var(--color-gray-900);
  --color-text-brand-main: var(--color-blue-500);
}

/* 3. СЕМАНТИЧЕСКИЙ УРОВЕНЬ: ТЕМНАЯ ТЕМА */
/* Переопределяем только семантику! Привязываем те же роли к другим цветам палитры */
[data-theme="dark"] {
  --color-bg-primary: var(--color-gray-900);
  --color-text-main: var(--color-white);
  --color-text-brand-main: var(--color-blue-400); /* Сделали синий чуть светлее для контраста */
}

/* ПРИМЕНЕНИЕ В КОМПОНЕНТЕ (Component Level) */
/* Компонент использует только семантику. Ему не нужно знать, какая сейчас тема. */

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

.button-primary {
  background-color: var(--color-text-brand-main);
  color: var(--color-bg-primary);
}

Т.е. для компонента нет разницы между темами — на визуальное оформление влияет только семантика, которую мы с вами создавали выше. Поэтому важно соблюдать нейминг, чтобы разработчикам было проще все это верстать. Заметили, как напрягся мозг, когда вы взглянули на код? То-то же, а разрабы с этим возятся по 8 часов в день...

Для элементов же, которые всегда белые (например, иконка закрытия на фото), используйте color-static-white. Этот токен не будет реагировать на смену темы!

Safety First: Как мы бережем нервы и продакшен при обновлении дизайн-системы

Обновление цветового токена в дизайн-системе через Deprecated и покраску в пурпурный цвет
Обновление цветового токена в дизайн-системе через Deprecated и покраску в пурпурный цвет

Давайте поговорим про то, как грамотно обновлять название или значение токена, чтобы не полетел прод, и чтобы все 5 дизайн-команд использовали актуальные токены.

Во-первых, устаревший токен нужно либо помечать тегом [DEP] — Deprecated, либо переносить в отдельную папку Deprecated, чтобы дизайнеры сразу видели, что токен устарел.

А для разработчиков токен нужно помечать через описание как @deprecated, вот пример:

"color-text-muted": {
 "value": "#71717A",
 "type": "color",
 "description": "@deprecated. Пожалуйста, используйте color-text-secondary"
 }

У фронтов стоит специальная утилита (например, Style Dictionary), которая берет этот JSON и конвертирует его в код. Когда утилита видит метку @deprecated в описании, она автоматически генерирует код с предупреждениями через console.warn.

Во-вторых, можно красить устаревшие токены в пурпурный цвет, чтобы дизайнеры сразу видели, что токен нужно переназначить.

Также нужно вести версионирование дизайн-системы, чтобы разработчикам и дизайнерам было проще отслеживать изменения:

v1.0.1 — мелкие фиксы: чуть-чуть изменили оттенок синего, код и названия не трогали. Ничего не сломается.

v1.1.0 — это добавление новых токенов (например, новые цвета для промо-блока). Старые не трогали. Прод в безопасности.

v2.0.0 — Breaking Changes (Ломающие изменения). Удалили старые токены, переименовали структуру (например, color-bg переделали в surface-bg). Вот такие обновления команды забирают осознанно, выделяя время на рефакторинг своего кода. Вы никогда не пушите Major-изменения молча.

Чтобы не случилась беда, фронтам нужно закладывать fallback-значения, которые будут применяться в случае поломки токена. Да, будет не так красиво, зато приложение запустится.

Задачки на закрепление материала

Чтобы вы точно запомнили, как правильно называть токены, рекомендую пройти несколько задачек на досуге и написать свои результаты в комментариях!

1. Найдите ошибку: Дизайнер назвал токен для цвета фона красной кнопки так: button-color-bg-danger. Как его нужно переписать по правилам нашей системы?

2. Семантика или Компонент? Токен называется spacing-stack-md. К какому уровню он относится и что делает?

3. Создайте токен (Семантика): Вам нужен токен для цвета текста, который сообщает об успешном действии (зеленый). Как вы его назовете?

4. Создайте токен (Семантика): Нужен токен для абсолютно круглых элементов (например, для бейджа с количеством уведомлений). Как назовем этот радиус?

5. Найдите ошибку: Разработчик создал токен для тени карточки при наведении: shadow-hover-card. Как правильно?

6. Создайте токен (Компонент): Нужно задать высоту для компонента input (поле ввода) маленького размера.

7. Паттерн on-: У нас есть семантический токен фона color-bg-warning (желтый). Как правильно назвать семантический токен для цвета иконки, которая будет лежать поверх этого фона?

8. Создайте токен (Компонент): Как назвать токен для цвета текста неактивной (disabled) главной кнопки (primary)?

9. Создайте токен (Компонент): Вам нужно задать внутренний отступ (padding) для выпадающего списка (dropdown). Размер отступа — маленький (sm).

10. Создайте токен (Компонент): Нужно поменять жирность шрифта (weight) специально для ценников (price) внутри карточек товаров.

Вы дошли до финального уровня, вас ждет Босс-файт!

11. Габариты vs Отступы: Дизайнер хочет задать расстояние между иконкой и текстом внутри кнопки. Он предлагает токен size-button-gap-sm. В чем его ошибка и как написать правильно?

12. Сложный компонент с деталью (Part): У нас есть компонент "Уведомление" (toast). Внутри него есть иконка закрытия (крестик). Как назвать компонентный токен для цвета этой иконки при наведении (hover)?  

13. Алиасы (Связи): Компонентный токен color-input-border-focus (цвет рамки инпута в фокусе) должен ссылаться на семантический токен. Какой семантический токен из категории "Бренд" (brand) подойдет сюда лучше всего?

14. Слои (Z-index): У нас есть модальное окно (z-index-modal). Внутри него открывается кастомный выпадающий список (dropdown). Как должен называться токен слоя для этого списка, чтобы он точно перекрыл модалку?

15. Комплексная задача*: Дизайнер собирает новую "Вторичную кнопку" (button-secondary). Она прозрачная, с серой рамкой. Напишите три компонентных токена для нее в дефолтном состоянии: для цвета фона, цвета рамки и цвета текста.

Ссылки для изучения нейминга токенов

Как и обещал, прикрепляю ссылки на доп. материалы, связанные с дизайн-токенами

Нейминг токенов в Shopify Polaris React

Нейминг дизайн-токенов в пинтерест

Design tokens – Material Design 3

How To Name Design Tokens in Design Systems – Smart Interface Design Patterns

Naming - Nord Design System

Цветовые токены в Radix UI

На этом все! Если было полезно — ставьте реакцию, а если захотите оставаться со мной на связи, то подписывайтесь на мой тгк «Банановый дизайн», где я периодически рассказываю о написании плагинов и продуктовом дизайне — никакой рекламы!

До скорого!