План привести дизайн-систему к тому, как надо, вырезав легаси. Правила — в Reference - UI Design System; здесь — диагноз с числами, что взято из разбора чужой системы, фазы работ и то, от чего отказываемся осознанно.
Повод: 04.08.2026, Макс — «Т.е. у нас вообще не должны мочь брать цвета из палитры. Мы можем брать цвета из РОЛИ» и «Режем, уничтожаем легаси, делаем как надо. Слишком часто это нам аукалось».
1. Диагноз: что есть на 04.08.2026
96 примитивов, 103 роли. Раскладка ролей вскрывает главное:
| Группа ролей | Штук |
|---|---|
| цвет | 86 |
| гарнитуры | 7 |
| контуры | 5 |
| габариты диалога | 3 |
| внутреннее поле панели | 1 |
Семантический ярус существует только для цвета. Длительности переходов, прозрачность
выключенного, зазоры со смыслом — ролей не имеют вовсе; компонент берёт их числом или ступенью
шкалы. Пример из свежего кода: длительность сдвига пункта меню написана как 0.12s прямо в правиле.
Семнадцать мест берут цвет мимо ролей (components.uss), из них девять — --gm-brass-300,
включая базовые кнопки. Это не единичная небрежность: правило живёт комментарием в шапке файла,
проверки нет, и нарушения копились месяцами. Последнее добавила я сама 04.08.2026, перенеся цвет
титула из старого кода не глядя.
Сироты копятся молча. Рампа ember осиротела при развороте палитры и была найдена глазами;
storm пересекается с patina по смыслу и до сих пор не разведён.
2. Что взято из Bloodlines-Dark-UI
Наша же дизайн-система для Asset Store (Assets/Alebardium/DesignSystem) решает те же задачи
дальше нас. Что оттуда стоит забрать, а что нет:
| Механизм там | Что делает | Берём? |
|---|---|---|
ThemeSchema отдельно от ThemeDefinition | список ролей отдельно от их значений → несколько тем поверх одного словаря | да, когда дойдём до нескольких стилей (фаза 5) |
ThemeDoctor | типизированные проблемы с автофиксом: роль не заполнена (Error), ссылка битая (Error), значение без роли — сирота (Info), шрифт не назначен (Warning) | частично: сироты и битые ссылки — фаза 4 |
| поиск «UI без темы» | находит элементы, не подключённые к ролям | да, это и есть наш гейт яруса (фаза 1) |
TextStyleTokenDef | кегль + межбуквенное + интерлиньяж + цвет одной ролью | нет: в USS эту роль играют классы |
InteractionTokenDef | все пять состояний + тайминг одним токеном на слот | нет как токен, да как идея: состояния компонента должны жить в одном месте (фаза 3) |
| слоты и блупринты | компонент объявляет цветные места, тема заполняет | нет: у нас USS-каскад, слоты избыточны |
3. Фазы
Порядок обязателен: каждая следующая опирается на предыдущую.
Фаза 1 — гейт яруса и резка легаси
ИСПОЛНЕНА. Гейт заведён 04.08.2026 (
TokenTierTests), переведено девятнадцать мест, заведено семь новых ролей — число «семнадцать» ниже относится к замеру на день написания плана и осталось как есть. Последний литерал цвета (зерно главного меню) снят 06.08.2026 ролью--gm-color-menu-grain: до этого дня гейт был красным. Тогда же исполнена и часть фазы 3 — состояния сведены в переченьUiComponentRegistryи закрыты гейтомUiStateGateTests.
- Тест: ступень палитры (
var(--gm-<рампа>-<число>)) вcomponents.ussи в экранных USS = красный, с именем файла и номером строки. Исключения — три вынужденных случая из справочника. - Починить семнадцать мест. Часть потребует новых ролей — это нормальный исход, а не обход: отсутствие роли означает дыру в словаре смыслов.
storm— развести сpatinaили удалить. Решение за Максом, откладывать больше нельзя: два токена с одним смыслом — это и есть «роль для галочки».
Результат фазы: взять цвет мимо роли становится невозможно, а не «не принято».
Фаза 2 — роли для не-цвета
Завести и применить: --gm-motion-* (длительности и кривые переходов), --gm-opacity-disabled,
именованные отступы там, где у зазора есть смысл («внутреннее поле панели», «шаг пунктов меню»).
Гейт фазы 1 на шкалы НЕ распространяется — см. «Шкалы против палитры» в справочнике.
Фаза 3 — компоненты
- Компоненты раскладки (
Stack/Section/ панель со слотами) — закрыть долг, из-за которого экран собирается из голыхVisualElement, а автор обязан помнить проflex-shrinkи прокрутку. Открыт с 04.08.2026, тянет за собой миграцию экранов. - Состояния компонента — в одном месте. Сейчас
:hover / :active / :focus / :disabledдублируются в каждом компоненте, и половина правил существует ради войны специфичности с темой Unity (.unity-button.gm-*). Свести к одному набору правил на семейство. - Инвентаризация: что уже компонент, что копипаста разметки, чего не хватает под ближайшие экраны.
Фаза 4 — перепись ролей (доктор в миниатюре)
Скрипт печатает: роли без единого потребителя, ссылки в никуда, ступени палитры, на которые не смотрит ни одна роль. Не тест, а инструмент уборки — красным быть не обязан.
Фаза 5 — несколько стилей (только когда понадобится)
Роли фиксированы, палитр может быть несколько (Макс: «палитра у нас может быть хоть 999999 цветов
под 4-6 стилей»). Предусловие — фаза 1: пока хоть один компонент висит на ступени, смена стиля
поедет наполовину. Механика — как ThemeSchema / ThemeDefinition в Bloodlines.
4. От чего отказываемся, и почему
- Component-токены (
--gm-button-primary-bgпод каждый компонент) — третий словарь, который надо синхронизировать с двумя. Каждый случай, где он «нужен», у нас означает нехватку роли. - Автоматический гейт контраста — решение Макса 04.08.2026: «лучше оставь это на мои глазочки… Без оверинженеринга». Следствие принимаем честно: числа контраста в комментариях USS перестают быть поддерживаемой правдой и читаются как ориентир на момент подбора. Если больно станет — вернёмся.
- Текстовый стиль одним токеном — в USS его роль уже играют классы.
- Слоты и блупринты — модель чужого рантайма (uGUI + инспектор), у нас USS-каскад.