Токен (token) — это переменная языка дизайна: цвет, размер шрифта, отступ, скругление, тень, длительность анимации получают имена в виде CSS-переменных --lh-*, а компоненты потребляют только имена и не записывают значения. Смена облика — это смена токенов.
Слой
Расположение
Количество
Момент вычисления
Переопределяемость
CSS-переменные · светлые
:root в styles/theme/common/var.scss
185 записей
runtime
✅ переопределяются как угодно
CSS-переменные · тёмные
[data-theme='dark'], .dark в styles/theme/common/var-dark.scss
118 записей
runtime
✅
SCSS-переменные
styles/theme/common/variables.scss
183 штуки
этап компиляции
⚠️ только правка исходников и пересборка
--lh-primary-color : # 2B4C7C ;
--lh-text-primary : rgba ( 0 , 0 , 0 , 0.88 );
--lh-border-color : # e5e6eb ;
--lh-text-primary : # E8E0D8 ;
--lh-border-color : # 3A3530 ;
Тёмная тема — это слой переопределения , а не отдельный набор: записываются только 118 токенов, которые нужно перевернуть; остальные наследуют светлые значения.
$lh-primary-color : # 2B4C7C !default ;
$lh-border-radius-base : 6 px !default ;
Назначение SCSS-переменных — участие в вычислениях на этапе компиляции : смешение цветов (mix() / shade()), компоновка теней (сложение нескольких shadow) — то, чего CSS-переменные не умеют. Плата за это — запекание на этапе компиляции , в тёмной теме они автоматически не переворачиваются.
Токены разделены на три уровня: первые два — в файлах глобальной темы, третий — в собственных стилях каждого компонента:
// 1. SCSS-переменные (variables.scss, этап компиляции)
$lh-primary : # 2B4C7C !default ;
$lh-text-primary : # 2C2C2C !default ;
// 2. Глобальные CSS-переменные (:root в var.scss, 190 записей)
--lh-primary-color : #{ $lh-primary } ;
--lh-text-primary : #{ $lh-text-primary } ;
// 3. Переменные уровня компонентов (собственные scss компонента; область действия — BEM-корень компонента)
--lh-card-bg : var ( --lh-bg-color , # FAF6F0 );
--lh-card-border-radius : calc ( var ( --lh-border-radius-base , 2 px ) + 2 px );
Ключевые механизмы:
Между 1-м и 2-м уровнями — интерполяция на этапе компиляции, а не цепочка ссылок var() : значение --lh-primary-color в сборку входит из $lh-primary; изменить SCSS-переменную в runtime невозможно (нужна пересборка). Промежуточного слоя «базовая палитра» в проекте нет — переменных вроде --lh-blue-6 для оттенков цвета не существует, семантические токены генерируются напрямую из SCSS-переменных.
Две точки опоры для смены облика : изменить SCSS-переменные в variables.scss и пересобрать (влияет на все семантические токены) или переопределить CSS-переменные на :root в runtime (этим путём идёт themeVars у ConfigProvider, действует мгновенно).
3-й уровень по умолчанию ссылается на 2-й : значения переменных уровня компонента по умолчанию представляют собой ссылки var() на глобальные токены (с fallback) — это и сохраняет связь с темой, и позволяет через themeVars точечно переопределить отдельный компонент.
Основные семантические домены (полная группировка — в таблице токенов ниже):
Домен
Типичные токены
Назначение
Основной цвет
--lh-primary-color / -hover / -active / -bg / -border
Брендовый основной цвет, набор из пяти
Текст
--lh-text-primary / -secondary / -tertiary / -disabled
Четырёхуровневая иерархия текста
Фон
--lh-bg-color / -page / -secondary / -overlay
Страница / контейнер / затемнение
Рамка
--lh-border-color / -light / -dark
Обводка
Состояния
--lh-success-color / -warning / -error / -danger / -info
Пять семантических цветов
Скругление
--lh-radius-small / -base / -large / -circle
Четыре шага скругления
Отступы
--lh-spacing-*
Шкала с базой 8px
Размер шрифта
--lh-font-size-*
Лестница размеров шрифта
Тень
--lh-shadow-*
Уровни теней
Анимация
--lh-animation-duration-* / -timing-function
Темп переходов
Декорация
--lh-decoration-color
Декоративный цвет в китайском стиле
主色与衍生语义 令牌 明色 暗色 SCSS 源 备注 --lh-primary-color #3D649E$lh-primary--lh-primary-color-hover #5078AB$lh-primary-hover--lh-primary-color-active #2B4C7C$lh-primary-active--lh-primary-color-bg color-mix(in srgb, var(--lh-primary-color) 25%, transparent)$lh-primary-light--lh-primary-color-border #2A3A4A$lh-primary-lighter--lh-color-on-primary #fff$lh-on-primary
状态 令牌 明色 暗色 SCSS 源 备注 --lh-hover-bg-color rgba(255, 255, 255, 0.08)$lh-hover-bg--lh-selected-color color-mix(in srgb, var(--lh-primary-color) 40%, #fff)—
功能色 令牌 明色 暗色 SCSS 源 备注 --lh-success-color #6FA36E$lh-success--lh-success-color-hover #82B581$lh-success-hover--lh-success-color-active #5B8C5A$lh-success-active--lh-success-color-bg #1A2A1A$lh-success-light--lh-warning-color #D4B76F$lh-warning--lh-warning-color-hover #E0C680$lh-warning-hover--lh-warning-color-active #C4A35A$lh-warning-active--lh-warning-color-bg #2A251A$lh-warning-light--lh-danger-color #C45050$lh-danger--lh-danger-color-hover #D46060$lh-danger-hover--lh-danger-color-active #B23A3A$lh-danger-active--lh-danger-color-bg #2A1A1A$lh-danger-light--lh-info-color #8F8F8F$lh-info--lh-info-color-hover #A0A0A0$lh-info-hover--lh-info-color-active #7A7A7A$lh-info-active--lh-info-color-bg #1A1A1A$lh-info-light
国风装饰色 令牌 明色 暗色 SCSS 源 备注 --lh-gold-color #D4A843$lh-gold--lh-gold-color-hover #E8C35C$lh-gold-hover--lh-gold-color-active #B8860B$lh-gold-active--lh-gold-color-bg #2A241A$lh-gold-light--lh-gold-color-border #3A2E1A$lh-gold-lighter--lh-vermilion-color #E85D4A$lh-vermilion--lh-vermilion-color-hover #FF7B6B$lh-vermilion-hover--lh-vermilion-color-active #C43A31$lh-vermilion-active--lh-vermilion-color-bg #2A1A18$lh-vermilion-light--lh-jade-color #7AAE7A$lh-jade--lh-jade-color-hover #9CC89C$lh-jade-hover--lh-jade-color-active #5B8C5A$lh-jade-active--lh-jade-color-bg #1A2A1A$lh-jade-light--lh-decoration-color rgba(212, 168, 67, 0.08)$lh-decoration-color
文本 令牌 明色 暗色 SCSS 源 备注 --lh-text-primary #E8E0D8$lh-text-primary--lh-text-regular #C8C0B8$lh-text-regular--lh-text-secondary #A09890$lh-text-secondary--lh-text-placeholder #7A7270$lh-text-placeholder--lh-text-disabled #5A5250$lh-text-disabled
边框 令牌 明色 暗色 SCSS 源 备注 --lh-border-color-base #3A3530$lh-border-color-base--lh-border-color-light #302B28$lh-border-color-light--lh-border-color-lighter #2A2520$lh-border-color-lighter--lh-border-color-extra-light #242018$lh-border-color-extra-light
圆角 令牌 明色 暗色 SCSS 源 备注 --lh-border-radius-base 沿用明色 $lh-border-radius-base--lh-border-radius-small 沿用明色 $lh-border-radius-small--lh-border-radius-round 沿用明色 $lh-border-radius-round--lh-border-radius-circle 沿用明色 $lh-border-radius-circle
背景 令牌 明色 暗色 SCSS 源 备注 --lh-bg-color #2A2520$lh-bg-color--lh-bg-color-page #1E1A16$lh-bg-color-page--lh-bg-color-disabled #242018$lh-bg-color-disabled--lh-bg-color-overlay rgba(10, 8, 6, 0.7)$lh-bg-color-overlay
阴影 令牌 明色 暗色 SCSS 源 备注 --lh-box-shadow-base 0 2px 12px 0 rgba(0, 0, 0, 0.5)$lh-box-shadow-base--lh-box-shadow-light 0 2px 4px 0 rgba(0, 0, 0, 0.4)$lh-box-shadow-light--lh-box-shadow-lighter 0 0 4px 0 rgba(0, 0, 0, 0.3)$lh-box-shadow-lighter
字体 令牌 明色 暗色 SCSS 源 备注 --lh-font-family 沿用明色 $lh-font-family--lh-font-size-extra-large 沿用明色 $lh-font-size-extra-large--lh-font-size-large 沿用明色 $lh-font-size-large--lh-font-size-medium 沿用明色 $lh-font-size-medium--lh-font-size-base 沿用明色 $lh-font-size-base--lh-font-size-small 沿用明色 $lh-font-size-small--lh-font-size-extra-small 沿用明色 $lh-font-size-extra-small--lh-font-weight-primary 沿用明色 $lh-font-weight-primary--lh-font-weight-bold 沿用明色 $lh-font-weight-bold--lh-font-line-height-primary 沿用明色 $lh-font-line-height-primary
组件级 · control 令牌 明色 暗色 SCSS 源 备注 --lh-control-height-mini 沿用明色 $lh-control-height-mini--lh-control-height-small 沿用明色 $lh-control-height-small--lh-control-height-medium 沿用明色 $lh-control-height-medium--lh-control-height-large 沿用明色 $lh-control-height-large--lh-control-height-x-large 沿用明色 $lh-control-height-x-large
间距 令牌 明色 暗色 SCSS 源 备注 --lh-spacing-xs 沿用明色 $lh-spacing-xs--lh-spacing-sm 沿用明色 $lh-spacing-sm--lh-spacing-md 沿用明色 $lh-spacing-md--lh-spacing-base 沿用明色 $lh-spacing-base--lh-spacing-lg 沿用明色 $lh-spacing-lg--lh-spacing-xl 沿用明色 $lh-spacing-xl--lh-spacing-xxl 沿用明色 $lh-spacing-xxl
层级 令牌 明色 暗色 SCSS 源 备注 --lh-z-index-normal 沿用明色 $lh-z-index-normal--lh-z-index-dropdown 沿用明色 $lh-z-index-dropdown--lh-z-index-sticky 沿用明色 $lh-z-index-sticky--lh-z-index-fixed 沿用明色 $lh-z-index-fixed--lh-z-index-modal-backdrop 沿用明色 $lh-z-index-modal-backdrop--lh-z-index-modal 沿用明色 $lh-z-index-modal--lh-z-index-popover 沿用明色 $lh-z-index-popover--lh-z-index-tooltip 沿用明色 $lh-z-index-tooltip
过渡 令牌 明色 暗色 SCSS 源 备注 --lh-transition-duration-fast 沿用明色 $lh-transition-duration-fast--lh-transition-duration-base 沿用明色 $lh-transition-duration-base--lh-transition-duration-slow 沿用明色 $lh-transition-duration-slow--lh-transition-function-ease-in-out 沿用明色 $lh-transition-function-ease-in-out
禁用态 令牌 明色 暗色 SCSS 源 备注 --lh-disabled-bg-color #242018$lh-disabled-bg-color--lh-disabled-text-color #5A5250$lh-disabled-text-color--lh-disabled-border-color #302B28$lh-disabled-border-color--lh-disabled-opacity 0.5$lh-disabled-opacity
组件级 · popover 令牌 明色 暗色 SCSS 源 备注 --lh-popover-bg-color #2A2520$lh-popover-bg-color--lh-popover-border-color #3A3530$lh-popover-border-color--lh-popover-border-radius 沿用明色 $lh-popover-border-radius--lh-popover-padding 沿用明色 $lh-popover-padding--lh-popover-title-color #E8E0D8$lh-popover-title-color--lh-popover-content-color #C8C0B8$lh-popover-content-color--lh-popover-arrow-size 沿用明色 $lh-popover-arrow-size
组件级 · popconfirm 令牌 明色 暗色 SCSS 源 备注 --lh-popconfirm-padding 沿用明色 $lh-popconfirm-padding--lh-popconfirm-icon-size 沿用明色 $lh-popconfirm-icon-size
组件级 · drawer 令牌 明色 暗色 SCSS 源 备注 --lh-drawer-bg-color #2A2520$lh-drawer-bg-color--lh-drawer-border-color #3A3530$lh-drawer-border-color--lh-drawer-header-padding 沿用明色 $lh-drawer-header-padding--lh-drawer-body-padding 沿用明色 $lh-drawer-body-padding--lh-drawer-footer-padding 沿用明色 $lh-drawer-footer-padding--lh-drawer-title-color #E8E0D8$lh-drawer-title-color--lh-drawer-close-size 沿用明色 $lh-drawer-close-size
组件级 · dropdown 令牌 明色 暗色 SCSS 源 备注 --lh-dropdown-bg-color #2A2520$lh-dropdown-bg-color--lh-dropdown-border-color #3A3530$lh-dropdown-border-color--lh-dropdown-border-radius 沿用明色 $lh-dropdown-border-radius--lh-dropdown-padding 沿用明色 $lh-dropdown-padding--lh-dropdown-item-height 沿用明色 $lh-dropdown-item-height--lh-dropdown-item-padding 沿用明色 $lh-dropdown-item-padding--lh-dropdown-item-color #C8C0B8$lh-dropdown-item-color--lh-dropdown-item-hover-bg-color var(--lh-hover-bg-color)$lh-dropdown-item-hover-bg-color--lh-dropdown-divider-color #302B28$lh-dropdown-divider-color
组件级 · message 令牌 明色 暗色 SCSS 源 备注 --lh-message-bg #2A2520$lh-message-bg-color--lh-message-border #3A3530$lh-message-border-color--lh-message-color #C8C0B8$lh-message-content-color--lh-message-shadow 沿用明色 $lh-message-shadow
组件级 · notification 令牌 明色 暗色 SCSS 源 备注 --lh-notification-bg #2A2520$lh-notification-bg-color--lh-notification-border #3A3530$lh-notification-border-color--lh-notification-title-color #E8E0D8$lh-notification-title-color--lh-notification-content-color #C8C0B8$lh-notification-content-color--lh-notification-width 沿用明色 $lh-notification-width--lh-notification-gap 沿用明色 $lh-notification-gap--lh-notification-shadow 沿用明色 $lh-notification-shadow
组件级 · loading 令牌 明色 暗色 SCSS 源 备注 --lh-loading-bg rgba(10, 8, 6, 62%)$lh-loading-bg-color--lh-loading-text-color #C8C0B8$lh-loading-text-color
组件级 · timeline 令牌 明色 暗色 SCSS 源 备注 --lh-timeline-line #302B28$lh-timeline-line--lh-timeline-dot var(--lh-info-color)$lh-timeline-dot--lh-timeline-timestamp var(--lh-text-secondary)$lh-timeline-timestamp
组件级 · collapse 令牌 明色 暗色 SCSS 源 备注 --lh-collapse-border #302B28$lh-collapse-border
组件级 · rate 令牌 明色 暗色 SCSS 源 备注 --lh-rate-active var(--lh-warning-color)$lh-rate-active
组件级 · segmented 令牌 明色 暗色 SCSS 源 备注 --lh-segmented-bg #242018$lh-segmented-bg
组件级 · calendar 令牌 明色 暗色 SCSS 源 备注 --lh-calendar-border var(--lh-border-color-lighter)$lh-calendar-border
组件级 · affix 令牌 明色 暗色 SCSS 源 备注 --lh-affix-z-index 沿用明色 $lh-affix-z-index
组件级 · backtop 令牌 明色 暗色 SCSS 源 备注 --lh-backtop-z-index 沿用明色 $lh-backtop-z-index
组件级 · menu 令牌 明色 暗色 SCSS 源 备注 --lh-menu-bg #242018$lh-menu-bg--lh-menu-padding 沿用明色 $lh-menu-padding--lh-menu-border #302B28$lh-menu-border--lh-menu-height 沿用明色 $lh-menu-height--lh-menu-collapse-width 沿用明色 $lh-menu-collapse-width--lh-menu-item-height 沿用明色 $lh-menu-item-height--lh-menu-item-padding 沿用明色 $lh-menu-item-padding--lh-menu-item-color var(--lh-text-primary)$lh-menu-item-color--lh-menu-item-hover-bg #302B28$lh-menu-item-hover-bg--lh-menu-item-active-color var(--lh-selected-color)$lh-menu-item-active-color--lh-menu-item-active-bg var(--lh-primary-color-bg)$lh-menu-item-active-bg--lh-menu-arrow-color var(--lh-text-secondary)$lh-menu-arrow-color--lh-menu-z-index 沿用明色 $lh-menu-z-index
组件级 · table 令牌 明色 暗色 SCSS 源 备注 --lh-table-bg #242018$lh-table-bg--lh-table-color var(--lh-text-regular)$lh-table-color--lh-table-header-bg #2A2420$lh-table-header-bg--lh-table-header-color var(--lh-text-primary)$lh-table-header-color--lh-table-border #302B28$lh-table-border--lh-table-row-hover-bg #2A2420$lh-table-row-hover-bg--lh-table-stripe-bg color-mix(in srgb, var(--lh-bg-color-page) 60%, transparent)$lh-table-stripe-bg--lh-table-cell-padding 沿用明色 $lh-table-cell-padding
组件级 · layout 令牌 明色 暗色 SCSS 源 备注 --lh-layout-header-height 沿用明色 $lh-layout-header-height--lh-layout-header-bg #242018$lh-layout-header-bg--lh-layout-aside-width 沿用明色 $lh-layout-aside-width--lh-layout-aside-bg #242018$lh-layout-aside-bg--lh-layout-main-bg #1C1815$lh-layout-main-bg--lh-layout-border #302B28$lh-layout-border
组件级 · row 令牌 明色 暗色 SCSS 源 备注 --lh-row-gutter 沿用明色 $lh-row-gutter
组件级 · tree 令牌 明色 暗色 SCSS 源 备注 --lh-tree-color #D8D0C8$lh-tree-color--lh-tree-padding 沿用明色 $lh-tree-padding--lh-tree-node-height 沿用明色 $lh-tree-node-height--lh-tree-node-hover-bg #2A2420$lh-tree-node-hover-bg--lh-tree-node-selected-color var(--lh-selected-color)$lh-tree-node-selected-color--lh-tree-node-selected-bg var(--lh-primary-color-bg)$lh-tree-node-selected-bg--lh-tree-arrow-color var(--lh-text-secondary)$lh-tree-arrow-color
组件级 · transfer 令牌 明色 暗色 SCSS 源 备注 --lh-transfer-panel-width 沿用明色 $lh-transfer-panel-width--lh-transfer-panel-height 沿用明色 $lh-transfer-panel-height--lh-transfer-bg #242018$lh-transfer-bg--lh-transfer-border #302B28$lh-transfer-border
组件级 · upload 令牌 明色 暗色 SCSS 源 备注 --lh-upload-bg #242018$lh-upload-bg--lh-upload-border var(--lh-border-color-base)$lh-upload-border--lh-upload-trigger-padding 沿用明色 $lh-upload-trigger-padding
组件级 · anchor 令牌 明色 暗色 SCSS 源 备注 --lh-anchor-color var(--lh-text-regular)$lh-anchor-color
组件级 · image 令牌 明色 暗色 SCSS 源 备注 --lh-image-viewer-mask rgba(0, 0, 0, 80%)—
无障碍焦点环 令牌 明色 暗色 SCSS 源 备注 --lh-focus-color #7FA6D9$lh-primary--lh-focus-ring-width 沿用明色 — --lh-focus-ring-offset 沿用明色 —
(Данные генерируются разбором трёх файлов токенов скриптом scripts/gen-docs-data.mjs; с количественными утверждениями: светлых 190, тёмных 118, SCSS 188; при несовпадении возникает ошибка.)
// themeVars у ConfigProvider (префикс --lh- добавляется к сокращённым ключам автоматически)
< lh - config - provider :theme - vars = " { 'primary-color': '#1677ff' } " >
Или записать CSS во входном файле приложения:
--lh-primary-color : # 1677ff ;
--lh-primary-color-hover : # 4096ff ;
--lh-primary-color-active : # 0958d9 ;
Подробнее см. Настройка в runtime .
// Входной scss проекта; переопределение до @use
$lh-primary-color : # 1677ff ;
@use ' @lh-ui/share/styles ' ;
Семантика !default — «не перекрывать, если значение уже есть», поэтому присвоения перед @use достаточно. Важно : это влияет только на ту часть, которая запекается на этапе компиляции; CSS-переменные в runtime нужно переопределять отдельно.
«Специальный выпуск по токенам высоты» состоялся (добавлены --lh-control-height-mini/small/medium/large/x-large;
button / select / input-number / cascader / tree-select / date-picker / time-picker /
input переведены на токены; input вместо производной от padding получил фиксированную высоту, асимметричный
padding-top: 16px для наличия метки, фиксированное смещение галочки checkbox и повторяющийся
хардкод translate(-50%,-50%) в switch исправлены). Что ещё предстоит обработать:
Размерные шаги spinner и icon с одинаковыми именами не совпадают (small 16 vs 14, medium 24 vs 16 и т. д.). Изменение любой стороны затронет всю библиотеку (message / notification / loading / все иконки); условие для запуска: жалобы на визуальные расхождения там, где в одном слоте смешиваются LhIcon / LhSpinner — тогда это выделяется в отдельный проект.
Размерные шаги выровнены не везде: select / switch имеют всего 3 шага, валидатор в date / time-picker сужен, у tree-select / rate / segmented / pagination нет size, а mini и x-large на уровне CSS почти не нарисованы (x-large есть только у avatar по всей библиотеке). Это изменения на уровне API, не связанные с токенами высоты.
Компонентам запрещено самостоятельно объявлять --lh-* : они могут только потреблять токены через var(--lh-*, fallback) (красная линия из корневого AGENTS.md). Новые токены добавляются в var.scss.
fallback обязателен : var(--lh-primary-color, #1677ff) — при отсутствии токена остаётся приемлемое значение по умолчанию; это контролируется пунктом 2 verify:styles (var fallback).
Полнота тёмной темы : добавляя токен, спросите «должен ли он перевернуться в тёмной теме», и если да — добавьте переопределение в var-dark.scss; это контролируется пунктом 7 verify:styles.
Токены со значением вида #{$lh-foo} запекаются на этапе компиляции : в тёмной теме они автоматически не переворачиваются и требуют явного перенаправления (см. Тёмная тема ).