콘텐츠로 이동

디자인 토큰

토큰(token)은 디자인 언어의 변수화입니다: 색, 글자 크기, 간격, 모서리 둥글기, 섀도, 애니메이션 지속 시간이 모두 --lh-*라는 CSS 변수로 명명되고, 컴포넌트는 이름만 소비하고 값을 쓰지 않습니다. 스킨을 바꾼다는 것은 토큰을 바꾸는 것입니다.

계층 위치 수량 평가 시점 덮어쓰기 가능성
CSS 변수 · 밝은색 styles/theme/common/var.scss의 :root 185개 런타임 ✅ 자유롭게 덮어쓰기
CSS 변수 · 어두운색 styles/theme/common/var-dark.scss의 [data-theme='dark'], .dark 118개 런타임 ✅
SCSS 변수 styles/theme/common/variables.scss 183개 컴파일 타임 ⚠️ 소스를 고쳐 재컴파일만 가능
: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개
}
[data-theme='dark'],
.dark {
--lh-bg-color: #2A2520;
--lh-text-primary: #E8E0D8;
--lh-border-color: #3A3530;
// ... 118개
}

어두운색은 별도의 한 벌이 아니라 덮어쓰기 계층입니다: 전환이 필요한 118개만 쓰고, 나머지는 밝은색 값을 따릅니다.

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

SCSS 변수의 용도는 컴파일 타임 계산에 참여하는 것입니다: 색 혼합(mix() / shade()), 섀도 합성(여러 층의 shadow를 더하는 것) 같은, CSS 변수로는 할 수 없는 일들입니다. 그 대가가 컴파일 타임에 구워진다는 것입니다 —— 어두운색에서 자동으로 전환되지 않습니다.

토큰은 세 단계로 나뉘며, 앞의 두 단계는 전역 테마 파일에, 세 번째 단계는 각 컴포넌트 자신의 스타일에 있습니다:

// 1. SCSS 변수(variables.scss, 컴파일 타임)
$lh-primary: #2B4C7C !default;
$lh-text-primary: #2C2C2C !default;
// 2. 전역 CSS 변수(var.scss의 :root, 190개)
--lh-primary-color: #{$lh-primary};
--lh-text-primary: #{$lh-text-primary};
--lh-bg-color: #FAF6F0;
// 3. 컴포넌트 수준 변수(컴포넌트 자신의 scss, 유효 범위는 컴포넌트의 BEM 루트)
.lh-card {
--lh-card-bg: var(--lh-bg-color, #FAF6F0);
--lh-card-border-radius: calc(var(--lh-border-radius-base, 2px) + 2px);
}

핵심 메커니즘:

  • 1, 2단계 사이는 컴파일 타임 보간이지 var() 참조 사슬이 아닙니다: --lh-primary-color의 값은 빌드 시에 $lh-primary에서 구워 들어오며, 런타임에 SCSS 변수를 바꾸는 것은 효과가 없습니다(재컴파일해야 함). 프로젝트에는 “기본 팔레트” 중간 계층이 없습니다 —— --lh-blue-6 같은 색단계 변수는 존재하지 않으며, 의미 토큰이 SCSS 변수에서 직접 생성됩니다.
  • 스킨 변경의 두 지렛대: variables.scss의 SCSS 변수를 바꾸어 재컴파일(모든 의미 토큰에 영향), 또는 런타임에 :root의 CSS 변수를 덮어쓰기(ConfigProvider의 themeVars가 이 길을 감, 즉시 효과).
  • 3단계는 기본적으로 2단계를 참조합니다: 컴포넌트 수준 변수의 기본값은 보통 전역 토큰의 var() 참조(폴백 포함)이며, 테마 연동을 유지하면서도 themeVars로 단일 컴포넌트를 목적지로 덮어쓸 수 있습니다.

주요 의미 도메인(전체 그룹은 아래 토큰 표 참고):

도메인 전형 토큰 용도
주색 --lh-primary-color / -hover / -active / -bg / -border 브랜드 주색의 5종 세트
글자 --lh-text-primary / -secondary / -tertiary / -disabled 4단계 글자 계층
배경 --lh-bg-color / -page / -secondary / -overlay 페이지 / 컨테이너 / 덮개
테두리 --lh-border-color / -light / -dark 외곽선
상태 --lh-success-color / -warning / -error / -danger / -info 5개의 의미 색
모서리 둥글기 --lh-radius-small / -base / -large / -circle 4단계 둥글기
간격 --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, 불일치 시 오류.)

// ConfigProvider의 themeVars(약식 키에 자동으로 --lh- 접두사 보충)
<lh-config-provider :theme-vars="{ 'primary-color': '#1677ff' }">

또는 애플리케이션 진입점에 CSS로 작성:

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

자세한 내용은 런타임 맞춤 설정을 참고하세요.

// 프로젝트 진입점 scss, @use 이전에 덮어쓰기
$lh-primary-color: #1677ff;
@use '@lh-ui/share/styles';

!default의 의미는 “이미 값이 있으면 덮어쓰지 않음”이므로, @use 이전에 할당하기만 하면 됩니다. 주의: 이것은 컴파일 타임에 구워지는 부분에만 영향을 주며, 런타임의 CSS 변수는 따로 덮어써야 합니다.

“높이 토큰 전문 작업”이 착지했습니다(--lh-control-height-mini/small/medium/large/x-large를 새로 만들고, button / select / input-number / cascader / tree-select / date-picker / time-picker / input이 모두 이 토큰을 참조하도록 변경, input은 padding에서 파생되던 것을 고정 높이로 바꾸고, has-label의 비대칭 padding-top: 16px, checkbox 체크 표시의 고정 오프셋, switch의 translate(-50%,-50%) 중복 하드코딩을 함께 수정). 여전히 남아 있는 것:

  1. spinner와 icon의 같은 이름 크기 단계가 일치하지 않습니다(small 16 vs 14, medium 24 vs 16 등). 어느 한쪽을 바꾸면 전 라이브러리에 파급됩니다(message / notification / loading / 모든 아이콘). 트리거 조건: 같은 슬롯에 LhIcon / LhSpinner를 섞어 쓸 때의 시각적 불만이 들어올 때, 그때 별도로 착수.
  2. size 단계가 고르지 않습니다: select / switch는 3단계만 있고, date / time-picker의 validator는 좁혀져 있으며, tree-select / rate / segmented / pagination에는 size가 없고, mini와 x-large는 CSS 계층에서 거의 그려지지 않았습니다(전 라이브러리에서 x-large가 있는 것은 avatar뿐). API 계층의 변경으로, 높이 토큰과는 분리되어 있습니다.
  • 컴포넌트가 스스로 --lh-*를 선언하는 것은 허용되지 않습니다: var(--lh-*, fallback)로만 소비(루트 AGENTS.md의 레드라인). 새 토큰은 var.scss에 추가합니다.
  • 폴백은 필수 작성: var(--lh-primary-color, #1677ff) —— 토큰이 없어도 받아들일 수 있는 기본값이 있으며, verify:styles의 2번째 항목(var fallback)이 관리합니다.
  • 어두운색 완전성: 새 토큰을 추가할 때 “어두운색에서 전환이 필요한가”를 자문하고, 필요하면 var-dark.scss에 덮어쓰기를 보충하며, verify:styles의 7번째 항목이 관리합니다.
  • 값이 #{$lh-foo} 형태인 토큰은 컴파일 타임에 구워진 것입니다: 어두운색에서 자동으로 전환되지 않으므로 반드시 명시적으로 다시 가리켜야 합니다(다크 모드 참고).

Copyright © 2024-2026 FengMo WenXue