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

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

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

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

3 уровня абстракции

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

✴️ Архитектура токенов (CTI)

На данный момент CTI (Category → Type → Item) — это самая популярная модель нейминга токенов. В этой модели важнее физическое свойство объекта, например, цвет, нежели сам объект.

Эта методология пришла из мира разработки и популяризирована инструментом Style Dictionary (главным конвертером токенов в код).

Вот гайд по неймингу дизайн-системы Amazon.

Дерево нейминга словаря Style Dictionary
Дерево нейминга словаря Style Dictionary
  1. Category (Категория) — определяет физическую природу (primitive nature) токена. Пример: color (цвет), size (размер), font (шрифт). Все токены внутри категории color всегда будут цветами, независимо от того, где они применяются.

  2. Type (Тип) — описывает, к какому свойству UI применяется эта категория. Пример: background (фон), text (текст), border (рамка).

  3. Item (Элемент) — указывает на конкретный элемент или компонент интерфейса. Пример: button (кнопка), dropdown (выпадающий список), container (контейнер).

  4. Sub-item (Подэлемент / Модификатор) — вариант или роль элемента. Пример: primary, secondary, success.

  5. State (Состояние) — интерактивное состояние. Пример: hover, active, disabled.

Оригинальная формула Style Dictionary: Category-Type-Item-Subitem-Statecolor-background-button-primary-active

✅ Плюсы CTI подхода:

  1. Когда первое слово токена — это его Категория (color, size, font), скриптам-компиляторам (тому же Style Dictionary) невероятно легко понять, с какими данными они работают.

  2. CTI — это дефолтная архитектура Style Dictionary. Разработчикам практически не нужно писать кастомные конфигурации и плагины для сборки проекта. Вы закидываете JSON, запускаете билд, и на выходе получаете готовые CSS-переменные, SCSS-миксины и Swift-файлы.

  3. В старых проектах, если фронтендеру нужно проверить все отступы в приложении, он просто вбивает в поиск по проекту $spacing- (или --spacing-) и видит абсолютно все переменные отступов в одном списке. Удобно для глобального аудита.

❌ Минусы CTI подхода:

  1. Главная боль современных разработчиков (особенно тех, кто пишет на React/Vue) в том, что в современной разработке компонент, например, button — это изолированная, самостоятельная сущность. При CTI-подходе стили этой кнопки размазаны по всей дизайн-системе:

    1. Цвет лежит в файле/папке colors.json (color-bg-button...)

    2. Отступы лежат в spacings.json (spacing-padding-button...)

    3. Скругления в radii.json (radius-button...)

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

  2. Разработчику, который верстает кнопку, плевать на префиксы color и background (он и так пишет CSS-правило background-color:). Ему важно быстро найти слово button и primary, а они зарыты в середине длиннющей «колбасы». Автокомплит в редакторе кода (IDE) тоже выдает тебе сначала тысячу цветов, и тебе приходится печатать половину токена, чтобы добраться до нужного компонента.

  3. Если бизнес решает переименовать компонент (например, modal в dialog), фронтендеру при CTI-подходе придется искать и переименовывать токены во множестве разных категорий (цвета, тени, z-index, отступы). Если бы на первом месте стоял компонент (dialog-bg-color, dialog-shadow), разработчик просто переименовал бы одну папку/группу.

Примеры нейминга CTI-подхода

Первый пример — это цвет фона кнопки:

структура токенов цвета фона в 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

✴️ Примеры построения структуры токенов (CTI)

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

Кнопка 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-значения, которые будут применяться в случае поломки токена. Да, будет не так красиво, зато приложение запустится.

✴️ Архитектура токенов (W3C / Объектно-ориентированный подход)

Сейчас набирает популярность новый стандарт, предложенный мировым консорциумом W3C (Design Tokens Community Group).

Важное уточнение: сам консорциум W3C (в своем драфте Design Tokens Format Module) стандартизирует именно древовидный JSON-формат (с использованием полей $value и $type). Однако внедрение этого формата породило в индустрии новый подход к текстовому неймингу — Объектно-Ориентированный Дизайн (OOD). Инструменты вроде Tokens Studio генерируют имена токенов, опираясь на вложенность групп стандарта W3C, из-за чего логика нейминга переворачивается (от Объекта к Свойству).

Здесь во главе угла стоит не физическое свойство (Цвет), а контекст или сам объект (Кнопка, Модалка, Фон, Текст). Мы идем от конкретного места в интерфейсе к инструменту его стилизации.

Дерево нейминга стандарта W3C

  • Component / Context (Компонент / Контекст) — главный объект, с которым мы работаем. Пример: button или input для компонентных токенов; bg или text для семантических.

  • Variant / Role (Вариант / Роль) — смысл или модификатор этого объекта. Пример: primary, danger, success.

  • Element (Элемент / Часть) — конкретная деталь сложного объекта (на семантическом слое часто опускается). Пример: icon (иконка внутри кнопки), label (текст внутри кнопки), track (дорожка у свитча).

  • Category (Категория / Свойство) — физическая природа (то самое свойство, которое мы меняем). W3C уносит его в конец! Пример: color (цвет), size (размер), space (отступ).

  • State (Состояние) — интерактивное состояние. Пример: hover, active, disabled.

Оригинальная формула W3C (Компонент): Component-Variant-Element-Category-State → button-primary-bg-color-hover

Оригинальная формула W3C (Семантика): Context-Role-Category-State → bg-danger-color-hover

Плюсы W3C подхода:

  • Идеальная инкапсуляция компонентов. Разработчик или дизайнер открывает папку button и видит там абсолютно всё: цвета, отступы, скругления, шрифты этой кнопки. Компонент собран в одном месте (изолирован), а не размазан по файлам colors, spacings и radii.

  • Идеальный UX в Figma Variables. Так как Категория (color) стоит в конце, в выпадающих списках Фигмы токены сразу группируются по контексту (bg, text, border). Дизайнер больше не путает цвета текста с цветами фона, потому что они лежат в разных логических папках, а не свалены в гигантскую корневую свалку «Color».

  • Прямой мэтч с логикой CSS. Фронтендерам привычнее мыслить от сущности к атрибуту. Мы пишем background-color, а не color-background. Токены читаются слева направо в точности так же, как пишутся стили в коде.

  • Легкий и безопасный рефакторинг. Если кнопку нужно переименовать или удалить из проекта, разработчик просто удаляет/переименовывает одну директорию button.

Минусы W3C подхода:

  • Сложнее для глобального аудита ресурсов. Если арт-директору нужно посмотреть все цвета в дизайн-системе разом, ему придется открывать по очереди папки bg, text, border, icon и папки компонентов, так как общей папки color больше нет.

  • Требует донастройки парсеров. Стандартные компиляторы (вроде старых версий Style Dictionary) по умолчанию ждут CTI. Чтобы они правильно поняли, что button-bg-color — это HEX, придется написать небольшие конфигурационные правила (transformers), чтобы скрипт определял тип данных по последнему слову токена, а не по первому.

  • Боль на старте для опытных команд. Если разработчики 10 лет писали $color-primary, переход на bg-primary-color сломает привычные паттерны и потребует времени на адаптацию всей команды.

✴️ Примеры нейминга W3C-подхода

Снова рссмотрим фон кнопки, но в контексте W3C:

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

Вы можете увидеть, что во главу угла встал компонент button, а color перенесли в конец.

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

В примере выше состояние hover самое последнее, так как это у цвета есть hover, а не наоборот. Это модификатор цвета.

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

Выше вы можете увидеть полный фарш со всеми основными свойствами и модификаторами.

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

И в конце рассмотрим скругление свитча в методологии W3C.

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

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

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

Гайд по неймингу CTI дизайн-системы Amazon

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

До скорого!