</>404 Dev Found

· дизайн · 7 мин чтения

Токены без драки: вопросы, которые стоит задать до первого переименования

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

Спор об имени токена почти никогда не про имя. Когда двое полчаса выясняют, surface или background, на самом деле они определяют, чьё это решение: дизайнера, который нарисовал, или разработчика, который будет это печатать следующие три года. Имя расходится по коду, макетам и документации, и поменять его потом дорого. Поэтому эмоций вокруг него больше, чем вокруг самих цветов.

Я собрал вопросы, которые обычно звучат в такие моменты, в порядке нарастания страха: сначала про имена, потом про слои, потом те, что задают шёпотом после встречи. Ответы короткие, мнение моё.


Часть первая: про имена

Как назвать токен, чтобы не пожалеть?

По назначению, а не по виду. Правило простое: имя не должно быть связано с визуальными свойствами. button-blue в день редизайна превращается в ложь, и у вас два плохих выхода: оставить враньё или переименовать всё сразу.

Роль переживает смену цвета. «Фон поверхности», «приглушённый текст», «тонкая граница»: эти фразы не зависят от оттенка, поэтому и имена из них получаются долговечные.

Из каких частей собирать имя?

Из категории и роли, а модификатор добавлять, только если без него не обойтись. Что-то вроде:

color.surface.default
color.text.muted
color.border.subtle

Цепочка «объект, категория, модификатор» встречается во многих системах, но обязательной полной цепочки никто не требует. Имя должно быть простым и без повторов. Если в нём три уровня, из которых два повторяют друг друга, лишний уровень просто уберите. Уровни «на вырост» я считаю самой невинной формой технического долга: никто не видит, как он копится.

**А если команда не может договориться, surface или background?**

Выберите любой и запишите. Серьёзно. Разница между этими словами в тысячу раз меньше цены месяца споров. Важнее, чтобы у слова было описание: $description в формате токенов существует как раз для этого. Одна строка «для чего это значение» убивает половину будущих обсуждений.

**Можно ли оставить blue-500 в имени?**

Можно, но только в слое сырых значений. Палитра оттенков ещё не семантика, это склад материалов. На складе номера уместны. На экране нет: компонент, который знает про blue-500, не знает, зачем ему этот синий.


Часть вторая: про слои и абстракции

Сколько слоёв нужно?

Начните с двух: сырые значения и роли. Третий добавляйте под конкретную нужду, а не из любви к порядку.

Здесь есть настоящий спор, и я не буду делать вид, что его нет. Material описывает три класса: reference с конкретными значениями, system с ролями и component для атрибутов элемента, причём компонентный указывает на системный. Часть практиков советует ограничиться двумя и компонентных токенов не заводить, потому что число сущностей растёт слишком быстро. Обе позиции живые. Я на стороне двух слоёв по умолчанию, и вот почему: удалить лишний слой сложнее, чем добавить недостающий.

Два слоя по умолчанию, третий по требованию
Два слоя по умолчанию, третий по требованию

Что случится, если начать сразу с компонентных токенов?

Получится каталог, в котором у каждой кнопки, карточки и поля есть свои токены, а выбрать значение для нового экрана не из чего. Ролей нет, значит, нет и точки опоры: дизайнер берёт токен соседнего компонента «потому что цвет подходит», и вы получаете связь, о которой никто не договаривался.

Как понять, что токену место в наборе?

Один вопрос: будет ли это значение когда-нибудь меняться? Если нет, это константа, а не токен. Токен нужен там, где решение хочется сделать явным и заменяемым: тема, плотность, бренд, режим. Всё остальное можно оставить обычным значением в стилях без всякой церемонии.

Добавлю то, что в таких заметках любят опускать: не всякая CSS-переменная является дизайн-токеном. Токен — именованное решение в общем формате (минимум это пара «имя — значение», тип необязателен), а переменная — один из способов его доставить. Когда эти понятия слипаются, в каталог попадает всё подряд, включая высоту хедера на одной странице.

Дубли: как они вообще появляются?

Тихо. Кто-то не нашёл нужный токен и завёл похожий. Через полгода в наборе два токена с неотличимыми по смыслу именами, и никто не помнит, какой правильный. Лучше всего помогает автоматика: проверка на повторяющиеся имена, на ссылки на сырые значения из компонентов и на циклы. Человеческая бдительность на ревью тут по опыту часто проигрывает. Если интересно, откуда берутся такие тихие расхождения в системах вообще, я писал про это в заметке про тропы, которые вытаптывают команды.


Часть третья: вопросы шёпотом

Что делать с устаревшими токенами? Удалить и забыть?

Не удалять, а помечать. В формате для этого есть $deprecated с необязательной причиной. Тогда команды видят, что токен уходит, и переезжают постепенно, а не в день релиза системы.

Выглядит это примерно так (значение условное: как именно в формате записывается цвет, зависит от версии спецификации, проверьте по документу):

{
  "color": {
    "$type": "color",
    "text": {
      "muted": {
        "$value": "{color.gray.600}",
        "$description": "Подписи, подсказки, второстепенный текст"
      },
      "secondary": {
        "$value": "{color.text.muted}",
        "$deprecated": "Заменён на color.text.muted"
      }
    }
  }
}

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

Где живёт правда: в макетах или в коде?

Честно: общего ответа нет. Редактор макетов умеет переменные, которые ссылаются друг на друга и имеют отдельные значения под режимы вроде светлой и тёмной темы. Код умеет CSS-переменные: они наследуются от родителя, а имена в них различают регистр, о чём забывают ровно один раз и надолго запоминают.

Я бы не спорил, кто главный, а настоял на одном: исходный набор один. Остальное генерируется. Сборщик вроде Style Dictionary делает из одного набора артефакты под разные платформы и языки. Две «истины», синхронизируемые руками, расходятся не потому, что люди плохие, а потому, что руки заняты другим. Про то, как вовремя понять, что системе вообще пора появляться, у меня есть отдельный чек-лист.

Формат токенов стабилен, значит, это стандарт?

Нет, и это важная оговорка. Формат впервые получил стабильную версию 2025.10, отчёт вышел 28 октября 2025 года. Но это отчёт сообщества при W3C, а не рекомендация консорциума. Поддержка в инструментах разная, поэтому перед тем, как строить на нём всё, проверьте, что ваш пайплайн его читает.

Токены сами дадут консистентность и темы?

Не дадут. Они лишь делают решение явным и заменяемым. Если решения нет, токен только красиво его назовёт. Тёмная тема на плохой системе ролей остаётся плохой тёмной темой, просто теперь её легче переключать.


Три вопроса на понедельник

Откройте свой набор и задайте ему то, что я задаю чужим:

  1. Есть ли в именах слова про цвет, размер или форму там, где должна быть роль?
  2. Ссылается ли хоть один компонент на сырое значение напрямую?
  3. Есть ли токены без описания и устаревшие без пометки?

Если на все три «нет», вы лучше большинства. Если хотя бы на один «да», это уже не повод для спора об именах, а список задач на ближайший спринт.