Aller au contenu

Jetons de conception

Un jeton (token) est la mise en variable du langage de conception : couleurs, tailles de police, espacements, angles arrondis, ombres et durées d’animation sont nommés en variables CSS --lh-* ; les composants ne consomment que des noms, jamais de valeur codée en dur. Changer de peau, c’est changer de jetons.

Couche Emplacement Quantité Le moment de l’évaluation Surcharge possible
Variables CSS · clair Le :root de styles/theme/common/var.scss 185 entrées À l’exécution ✅ Surcharge libre
Variables CSS · sombre Le [data-theme='dark'], .dark de styles/theme/common/var-dark.scss 118 entrées À l’exécution ✅
Variables SCSS styles/theme/common/variables.scss 183 variables À la compilation ⚠️ Seulement en modifiant la source et en recompilant
:root {
--lh-primary-color: #2B4C7C;
--lh-text-primary: rgba(0, 0, 0, 0.88);
--lh-bg-color: #FAF6F0;
--lh-border-color: #e5e6eb;
--lh-radius-base: 6px;
--lh-spacing-base: 8px;
// ... 185 entrées
}
[data-theme='dark'],
.dark {
--lh-bg-color: #2A2520;
--lh-text-primary: #E8E0D8;
--lh-border-color: #3A3530;
// ... 118 entrées
}

Le mode sombre est une couche de surcharge, et non un jeu indépendant : on n’écrit que les 118 entrées qui doivent se retourner, les autres conservent la valeur claire.

$lh-primary-color: #2B4C7C !default;
$lh-border-radius-base: 6px !default;
// ... 183 variables

L’usage des variables SCSS est de participer aux calculs de compilation : le mélange de couleurs (mix() / shade()), la composition des ombres (l’addition de plusieurs couches de shadow), ce que les variables CSS ne peuvent pas faire. Le prix à payer est la cuisson à la compilation — aucun retournement automatique en mode sombre.

Les jetons sont répartis en trois paliers : les deux premiers dans les fichiers globaux du thème, le troisième dans les styles propres de chaque composant :

// 1. Les variables SCSS (variables.scss, à la compilation)
$lh-primary: #2B4C7C !default;
$lh-text-primary: #2C2C2C !default;
// 2. Les variables CSS globales (le :root de var.scss, 190 entrées)
--lh-primary-color: #{$lh-primary};
--lh-text-primary: #{$lh-text-primary};
--lh-bg-color: #FAF6F0;
// 3. Les variables au niveau du composant (le scss du composant lui-même ; la portée est la racine BEM du composant)
.lh-card {
--lh-card-bg: var(--lh-bg-color, #FAF6F0);
--lh-card-border-radius: calc(var(--lh-border-radius-base, 2px) + 2px);
}

Les mécanismes clés :

  • Entre les paliers 1 et 2, il s’agit d’une interpolation à la compilation, et non d’une chaîne de références var() : la valeur de --lh-primary-color est cuite à partir de $lh-primary au moment de la construction ; modifier la variable SCSS à l’exécution est sans effet (il faut recompiler). Il n’y a pas de couche intermédiaire « palette de base » dans le projet — pas de variables de gamme de couleurs du type --lh-blue-6 ; les jetons sémantiques sont directement générés à partir des variables SCSS.
  • Les deux leviers du changement de peau : modifier la variable SCSS de variables.scss et recompiler (cela affecte tous les jetons sémantiques), ou surcharger à l’exécution les variables CSS du :root (c’est la voie qu’empruntent les themeVars du ConfigProvider, qui prend effet immédiatement).
  • Le palier 3 référence le palier 2 par défaut : la valeur par défaut d’une variable au niveau du composant est généralement une référence var() vers un jeton global (avec repli), ce qui maintient la liaison avec le thème tout en permettant à themeVars de surcharger un seul composant de façon ciblée.

Les principaux domaines sémantiques (le regroupement complet est dans la table des jetons ci-dessous) :

Domaine Les jetons typiques Usage
La couleur primaire --lh-primary-color / -hover / -active / -bg / -border Le quintette de la couleur primaire de marque
Le texte --lh-text-primary / -secondary / -tertiary / -disabled Les quatre niveaux de hiérarchie du texte
Le fond --lh-bg-color / -page / -secondary / -overlay La page / les conteneurs / le voile
La bordure --lh-border-color / -light / -dark Les traits
Les états --lh-success-color / -warning / -error / -danger / -info Les cinq couleurs sémantiques
Les angles arrondis --lh-radius-small / -base / -large / -circle Les quatre paliers d’arrondi
Les espacements --lh-spacing-* La graduation sur la base de 8px
Les tailles de police --lh-font-size-* L’échelle des tailles de police
Les ombres --lh-shadow-* La hiérarchie des ombres
Les animations --lh-animation-duration-* / -timing-function Le rythme des transitions
L’ornement --lh-decoration-color La couleur d’ornement style chinois

主色与衍生语义

令牌明色暗色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 沿用明色—

(Les données sont générées par scripts/gen-docs-data.mjs en analysant les trois fichiers de jetons, avec des assertions de quantité : 190 clairs, 118 sombres, 188 SCSS ; tout écart fait échouer.)

// Les themeVars du ConfigProvider (les clés abrégées reçoivent automatiquement le préfixe --lh-)
<lh-config-provider :theme-vars="{ 'primary-color': '#1677ff' }">

Ou écrire du CSS à l’entrée de l’application :

:root {
--lh-primary-color: #1677ff;
--lh-primary-color-hover: #4096ff;
--lh-primary-color-active: #0958d9;
}

Voir Personnalisation à l’exécution.

// Le scss d'entrée du projet ; la surcharge se fait avant le @use
$lh-primary-color: #1677ff;
@use '@lh-ui/share/styles';

La sémantique de !default est « ne pas surcharger si une valeur existe déjà » ; il suffit donc d’assigner avant le @use. À noter : cela n’affecte que la partie cuite à la compilation ; les variables CSS à l’exécution doivent encore être surchargées par ailleurs.

Le « chantier des jetons de hauteur » a été livré (ajout des --lh-control-height-mini/small/medium/large/x-large, button / select / input-number / cascader / tree-select / date-picker / time-picker / input référencent tous les jetons, input passe d’une hauteur dérivée du padding à une hauteur fixe, et le padding-top: 16px asymétrique des has-label, le décalage fixe de la coche de checkbox, ou encore la répétition codée en dur du translate(-50%,-50%) de switch ont été corrigés en même temps). Ce qui reste à traiter :

  1. Les paliers de taille ne sont pas alignés entre spinner et icon (small 16 contre 14, medium 24 contre 16, etc.). Modifier un côté ou l’autre impacte toute la bibliothèque (message / notification / loading / toutes les icônes) ; déclencheur : une remontée visuelle de mélange LhIcon / LhSpinner dans un même emplacement ; le cas échéant, un sujet dédié sera ouvert.
  2. Les paliers de size sont inégaux : select / switch n’ont que 3 paliers, le validator de date / time-picker est verrouillé, tree-select / rate / segmented / pagination n’ont pas de size, et mini / x-large sont presque jamais tracés dans la couche CSS (sur toute la bibliothèque, seul avatar possède x-large). C’est un changement de la couche API, découplé des jetons de hauteur.
  • Un composant n’a pas le droit de déclarer lui-même un --lh-* : il ne peut que consommer via var(--lh-*, fallback) (ligne rouge du AGENTS.md racine). Les nouveaux jetons s’ajoutent dans var.scss.
  • Le fallback est obligatoire : var(--lh-primary-color, #1677ff) — en l’absence du jeton, une valeur par défaut acceptable subsiste ; la vérification 2 de verify:styles (var fallback) veille.
  • L’exhaustivité du mode sombre : pour tout nouveau jeton, se demander « doit-il se retourner en mode sombre ? » et, si oui, ajouter la surcharge dans var-dark.scss ; la vérification 7 de verify:styles veille.
  • Un jeton dont la valeur est de la forme #{$lh-foo} est cuit à la compilation : il ne se retourne pas automatiquement en mode sombre et doit être explicitement redirigé (voir Mode sombre).

Copyright © 2024-2026 FengMo WenXue