Skip to content

定制主题 ​

赞助

Vue Amazing UI 的主题在颜色维度有四层配置面:7 个颜色种子(改整套)→ 组件级主色 theme.components(改某个组件的整套主色)→ 全局语义变量 --va-*(改某个作用域)→ 组件令牌(改单个视觉面);此外还有模式维度(theme.mode)与组件实例自身的 prop / style(见 ConfigProvider 的配置面)。默认颜色全部由派生函数按种子计算,组件样式只消费语义变量 --va-*,因此改一个种子,常态 / 悬停 / 按下 / 浅底 / 描边会同步变化。


派生规则:每个种子色先摊成 10 级色阶(第 1 档最浅、第 10 档最深),再按固定档位映射语义角色 —— 浅底取第 1 档、描边第 3 档、链接悬停第 4 档、悬停第 5 档、常态与主色文字第 6 档、按下第 7 档。暗色的色阶方向相反,悬停 / 按下改取第 7 / 5 档(链接悬停两模式共用悬停档),常态与主色文字仍取第 6 档。


默认主题色为

#1677ff
,无需任何配置。

本页说明概念、派生规则与变量清单;可交互演示与 API 见 ConfigProvider。

术语说明:种子 / 派生 / 变量 / 令牌 ​

术语定义对应代码
种子(seed)一整套色阶的起点色,共 7 个theme.seed.primary = '#1677ff'
派生由起点色计算出一整组深浅(常态 / 悬停 / 按下 / 浅底 / 描边)derive(seed, mode),库内部完成
变量(--va-*)派生结果落地为 CSS 变量,组件只读取变量--va-primary-color 等 42 个
令牌(--va-<组件>-*)组件内部细节的公开变量名,用于单点覆盖--va-slider-handle-shadow-color

核心结论:给定 7 个种子,42 个变量由库派生,组件只消费变量;因此换肤不重建组件,也不产生运行时开销。

主题模型:种子 → 派生 → 变量 ​

本节先给出派生模型,下文所有用法都基于它:种子 → 派生 → 42 个 CSS 变量 → 组件只读变量。

text
seed + mode ──┐
              ├─→ derive(seed, mode) ─→ 42 个 --va-* ─┐
components ───┘         │                            ├─→ 写到作用域节点 ─→ CSS 继承 ─→ var(--va-*)
                        └─→ 组件令牌 --va-<comp>-* ─┘     · 包裹元素 / <html> / 浮层根节点

关键点:JS 只算一次、写一次,染色全在 CSS 引擎里完成。换主色时实际只变 15 个变量(主色 6 + info 3 + 链接 3 + 焦点环 1 + 品牌色暗底 2),其余 27 个连值都不变;暗色不是第二套种子,而是 derive 的另一个入参。

作用域与载体 ​

载体影响范围适用场景
ConfigProvider 包裹元素(abstract: false,默认)自身子树局部换肤;SSR 首帧即可序列化
<html>(abstract: true)整页,含页面链接与全部浮层应用级主题,最外层传一次
浮层根节点(库自动转发)该弹层无需配置,作用域内的弹窗 / 下拉自动跟随
任意祖先选择器上的 --va-*该子树只改某个变量或某个组件令牌

优先级链 ​

text
组件实例 prop / style(行内)
  > 最近一层祖先上的组件令牌
    > theme.components(写在作用域节点)
      > seed 派生的全局变量
        > 静态默认表

同一个变量冲突时按普通 CSS 级联处理;--va-button-primary-color 与 --va-primary-color 之间不是优先级,而是 var(a, b) 的回退顺序。

排查清单:颜色没生效 ​

现象先查
只有这一个组件不对是否被实例 style / color prop 等更高优先级覆盖
悬停或按下跳回默认色只覆盖了常态,需整组覆盖(常态 / 悬停 / 按下)
弹窗 / 下拉没跟随作用域模式下是否在 Provider 子树内;应用级主题是否用了 abstract: true
暗色只变了一半纯 CSS 切暗色时 data-va-mode 必须写在实际作用域节点上
覆盖了组件令牌但无效该视觉面是否已公开(见组件级令牌),是否写在 <style> 声明而非消费处
自定义 SVG 不变色fill 是 presentation attribute,不解析 var(),请写进 style

构建期静态表、三张变量表、内部桥与公开令牌的双写约定、Teleport 转发协议、verify:theme 守护等实现细节,属于贡献者文档,见仓库 development/theme-system.md;面向使用者的结论已全部收在本页。

颜色种子:seed ​

修改种子后的联动效果:种子换色、语义种子

种子默认值说明
primary#1677ff品牌主色
success#52c41a成功色
warning#faad14警告色
error#ff4d4f错误 / 危险色
info跟随 primary信息色;未传时复用主色的三件套
neutralText#000000中性文本基准(透明度阶梯的叠加色)
neutralBg#ffffff中性背景基准(显式传入时两个模式共用)

种子只接受不透明的 #rgb / #rrggbb(#rrggbbff 会收敛为 6 位);半透明(如 #1677ff80)会被判为非法并在开发环境告警、回退该字段默认值,不会中断其余字段的派生 —— 否则色阶基色会变成半透明,按钮底色与文字对比度全部失真。

组件级主色:theme.components ​

只覆盖某个组件的主题色,其余组件仍用全局种子;组件配置优先于 seed

旧版 theme.Button.primaryColor 的能力由 theme.components 承接:这里只放通用主色,组件内部的细分令牌(如 Slider 的 rail / tooltip、Button 的 ripple)仍是 CSS 变量、不在 components 配置面里,需要时用组件级令牌覆盖。

vue
<script setup lang="ts">
import type { ConfigProviderTheme } from 'vue-amazing-ui'
const theme: ConfigProviderTheme = {
  seed: { primary: '#1677ff' },
  components: {
    Button: { primaryColor: '#18a058' },
    Slider: { primaryColor: '#18a058' }
  }
}
</script>
<template>
  <ConfigProvider :theme="theme">
    <Button type="primary">Button 使用组件主色</Button>
    <Slider :value="40" />
  </ConfigProvider>
</template>
  • 组件配置优先于 seed:Button 用 #18a058 派生,其余组件仍用 #1677ff;
  • 组件主色与 seed 共用同一校验口径:接受 #rgb / #rrggbb / #rrggbbff(alpha 必须为 ff),非法值告警并忽略该组件配置;
  • 当前有 40 个组件接入了组件级主色(完整清单见组件级令牌),覆盖对外暴露的主色使用点;组合组件内的子组件与派生组件(如 DropdownButton 的分割线)跟随宿主组件的令牌,不单独配置。未接入的组件(如 Dropdown)写入键名会在开发环境告警、不会静默生效,需要时用组件令牌或嵌套作用域;
  • 运行期移除某个组件的配置(整体替换 theme,或删掉 components.Button)会回落到 seed;
  • 组件配置写在 ConfigProvider 的作用域节点上(abstract: false 写包裹元素,abstract: true 写 <html>),优先级高于 seed 与外层祖先的 --va-primary-*。Button / Slider / Menu 仍可在更近的元素上覆盖公开组件令牌;其余组件要再覆盖时,请用更内层的 ConfigProvider 重新配置该组件;
  • 组件配置沿 DOM 继承:外层设置的 components.Button 会继续作用于内层;内层只改 seed 不会把它重置,需要重置时在内层显式设置该组件的 primaryColor;
  • 组件主色按 Provider 解析出的 mode 派生;如果页面是用纯 CSS data-va-mode 切暗色、而 Provider 没有 mode,请补传 mode,否则组件主色会按浅色色阶派生;
  • 组件级主色只影响该组件自身的主色使用点;组合组件内的子组件(如 InputSearch 内的 Input、Popconfirm 内的 Button)按子组件自己的 theme.components 配置,需要时分别配置;
  • abstract: true 时组件配置要和 seed / mode 放在同一个 Provider 上;只有组件配置时请用 abstract: false,否则它不参与 <html> 写入,开发环境会告警;
  • 配置 Button / Slider / Menu 时,Provider 会同时写出内部桥与公开令牌(同一份派生结果的两套名字),组件样式只读其中一套;两种入口最终落到同一个变量,实现细节见仓库 development/theme-system.md 的「组件级主色怎么落地」;
  • 在线演示:组件级主色。

运行期切换:响应式 theme ​

修改种子即可,推荐用 computed 派生;整体替换 theme 对象或就地改写 seed 字段都会生效

vue
<!-- App.vue -->
<script setup lang="ts">
import { computed, ref } from 'vue'
import type { ConfigProviderTheme } from 'vue-amazing-ui'
const primary = ref<string>('#ff6900')
const theme = computed<ConfigProviderTheme>(() => ({
  seed: { primary: primary.value }
}))
</script>
<template>
  <!-- 应用级主题:显式 abstract=true,变量写到 <html>,浮层与页面链接一并跟随 -->
  <ConfigProvider :abstract="true" :theme="theme">
    <RouterView />
  </ConfigProvider>
</template>

明暗模式:light / dark / auto ​

mode 是派生函数的入参,不是第二套种子;dark 与 light 共用同一组种子

vue
<script setup lang="ts">
import { ref } from 'vue'
import type { ConfigProviderTheme, ThemeMode } from 'vue-amazing-ui'
const mode = ref<ThemeMode>('light')
const theme = ref<ConfigProviderTheme>({ mode: mode.value })
</script>
<template>
  <ConfigProvider :abstract="true" :theme="theme">
    <RouterView />
  </ConfigProvider>
</template>
  • mode="light" | "dark":显式指定;
  • mode="auto":跟随系统 prefers-color-scheme,变化时自动重写变量,卸载后解除监听;
  • 未传 mode:沿用外层作用域(最外层为浅色);
  • 在线演示:明暗模式切换。

最外层只切 mode 而未传 seed(也没有可继承的种子)时,Provider 不会写任何变量,而是把 data-va-mode 写到作用域节点上,由静态默认表接管 —— 因此切换暗色是纯 CSS 行为,零样式重建。

暗色表同时输出 color-scheme: dark(浅色表对应的 [data-va-mode='light'] 输出 color-scheme: light),原生滚动条、表单控件与默认背景会随模式切换。

mode="auto" 在 SSR 下的首帧

服务端拿不到 prefers-color-scheme,此时下发任何模式都会和客户端首次渲染不一致(hydration mismatch)。因此 abstract: false + mode="auto" 时,首帧不下发变量与 data-va-mode,由客户端挂载后补写;服务端首帧会用静态默认表(浅色)。需要首帧即暗色时,请在 SSR 侧显式传 mode="dark"。

默认的 abstract: false 会把变量序列化进包裹元素,SSR 首帧即正确;abstract: true 不产出可序列化的变量(变量在客户端挂载后写 <html>),首帧沿用静态默认表。

作用域换肤:嵌套 ConfigProvider ​

主题沿 DOM 级联:在某个区域外层再包一个 ConfigProvider,换肤只作用于该子树

vue
<template>
  <ConfigProvider :theme="{ seed: { primary: '#1677ff' } }">
    <Button type="primary">外层主色</Button>
    <ConfigProvider :abstract="false" :theme="{ seed: { primary: '#18a058' } }">
      <Button type="primary">子树主色</Button>
    </ConfigProvider>
  </ConfigProvider>
</template>
  • 默认 abstract: false:实例渲染包裹元素,变量与 data-va-mode 写在该元素上,只作用于自身子树,SSR 首帧可直接序列化;
  • Teleport 到 body 的浮层(弹窗 / 下拉 / 消息等)由边界转发补齐:浮层根节点带上当前作用域的令牌与模式,因此作用域内的浮层也跟随,不会退回静态默认表;
  • 需要页面级生效(主题化 body 级链接、body 背景等)时,在最外层传 :abstract="true",由它把变量写到 <html>;
  • 「<html> 写入者」按是否配置了全局主题域(种子或模式)判定:只配置 theme.components 的实例不参与写入权仲裁(abstract: true 时会告警,应用级组件配置请与 seed / mode 同层);未传 theme(或传空对象)的 ConfigProvider 不占用该名额,因此应用根部放一个空主题实例,不会让页面里的主题实例失效;
  • 嵌套实例未显式传 mode 时继承外层模式(暗色区域内的子作用域不会派生出浅色变量);
  • 嵌套实例未显式传 seed 时继承外层种子(「外层换品牌色 + 内层只切暗色」不会退回默认蓝);传了则整体替换,不做逐字段合并;
  • 组件级配置写在同一个作用域节点上:内层 Provider 的 theme.components 覆盖外层;宿主要在组件配置之上再覆盖,请写在更靠近组件的元素上,或用组件实例 prop;
  • 嵌套实例若显式传 abstract: true(无包裹元素),没有可承载变量的节点,只能随外层生效,开发环境会告警;
  • 作用域标记在组件 setup 时确定:运行期给父级增删主题不会改变已挂载子级的判定(例如父级随后移除主题,子级不会接管 <html>)。需要动态切换时请重新挂载子树,或改用 abstract: false 的分层作用域;
  • 在最外层只切 mode、且没有可继承的种子时,Provider 不写任何变量,只写 data-va-mode:静态表已按模式声明全量变量(含 [data-va-mode='light'] 回环),宿主对 :root 单变量的覆盖不会被遮蔽;
  • 在线演示:作用域换肤。

单变量覆盖:--va-* ​

--va-* 是公开契约,宿主可直接在任意作用域覆盖

css
.my-panel {
  --va-primary-color: #ff6900;
  --va-primary-color-hover: #d95a00;
  --va-primary-color-active: #b34b00;
}

WARNING

只覆盖 --va-primary-color 而不覆盖 -hover / -active,会出现「常态变了、悬停没变」。换色应通过 ConfigProvider.seed 派生整套;只想改某个组件时用 theme.components.<Component>.primaryColor;或在同一作用域同时覆盖完整状态变量。

颜色变量清单:42 个 --va-* ​

共 42 个;新增变量必须同时满足「不是现有变量的函数」与「至少有一个组件消费」

分组变量
主色--va-primary-color / -hover / -active;--va-primary-bg-color / --va-primary-border-color / --va-primary-text-color
语义色--va-{success,warning,error,info}-color / -bg-color / -border-color
文本--va-text-color-1 / -2 / -3 / --va-text-color-solid / --va-text-color-disabled
背景--va-bg-container-color / --va-bg-elevated-color / --va-bg-layout-color / --va-bg-spotlight-color / --va-bg-brand-dark-color / --va-bg-brand-dark-deep-color
边框--va-border-color / --va-border-split-color
填充--va-fill-color-1 / --va-fill-color-2 / --va-fill-color-3 / --va-fill-color-4
阴影--va-shadow-color / --va-focus-shadow / --va-popup-shadow
遮罩--va-mask-color
链接--va-link-color / -hover / -active
  • --va-primary-text-color / --va-link-* 与主色同值,不做对比度改写;--va-primary-text-color 的消费面是「主色文字」场景(Menu 选中项、Tabs 激活页签、Pagination 当前页),单独覆盖它可以把「色块」与「文字」的取色拉开;
  • --va-text-color-solid 是实色底(彩色底 / 黑色遮罩)上的文字色,两种模式恒为白;按钮主色底、Badge 计数、Avatar、图片预览的白色 chrome 都取它;
  • --va-bg-elevated-color 是浮层底(浅色 #ffffff / 暗色 #1f1f1f):暗色下它比 --va-bg-container-color 提亮一档,Modal / Drawer / Message / Notification / Dialog / Popover / Popconfirm / Dropdown / Select 面板 / 日期面板 / ColorPicker 面板都取它,否则浮层与页面同色、层级无法分辨;
  • --va-bg-spotlight-color 是反色浮层底(浅色 rgba(0,0,0,.85) / 暗色 #424242),Tooltip 默认取它;
  • --va-bg-brand-dark-color / --va-bg-brand-dark-deep-color 是品牌色暗底(默认主色下 #001129 / #000a17):取主色的色相与饱和度、亮度压到 8% / 4.5%,两个模式取值相同。Menu 的 theme="dark" 皮肤取它们做根列表 / 浮层面板与内联子菜单的底色,因此换主题色时深色皮肤跟着变色相;配置了 theme.components.Menu.primaryColor 时按该组件主色重新派生(优先于 seed);是否启用这套皮肤仍只由 theme 属性决定,与 data-va-mode 无关;
  • --va-mask-color 两模式固定 rgba(0, 0, 0, 0.45),Modal / Drawer / 图片预览的遮罩都取它(遮罩不跟随正文色,否则暗色下会变成白色蒙层);
  • --va-fill-color-3 是最强的一档中性叠加(浅色 rgba(0,0,0,.15) / 暗色 rgba(255,255,255,.18)),Watermark 的默认水印色取它,因此暗色下自动变成半透明白;显式传 textStyle.color 时以传入值为准;
  • --va-fill-color-4 是最淡的一档中性叠加(浅色 rgba(0,0,0,.02) / 暗色 rgba(255,255,255,.04)),用于默认标签底、Result 内容区底纹、表格展开行;
  • 编号 1~4 只表示档位,不代表强度顺序(3 最强、4 最淡);
  • 阴影变量是完整 box-shadow 值,直接整体赋值即可;
  • --va-shadow-color 是方向性 / 局部阴影的基色(浅色极淡黑、暗色加深);不要拿 --va-fill-color-2 当阴影色,它在暗色下是白色,会形成光晕;
  • 例外是落在自身遮罩上的面板阴影(如 Drawer 的四向面板):遮罩在暗色下已是 rgba(0,0,0,.45) 的深色叠加,再用加深的基色会在面板与遮罩交界处叠出一条黑边,这类阴影改用固定 rgba(0,0,0,.08) 基色。

关于可读性

系统不替品牌色兜底。如果主色偏浅(如黄色、亮青),主色文字与主色按钮上的白字对比度会不足 —— 这时应当换一个更深的品牌色(或单独覆盖 --va-primary-text-color / --va-text-color-solid),而不是期待主题系统自动修正。

脚本取色:derive ​

组件样式只读 CSS 变量;需要在 JS / canvas / SVG 里拿到同一份色值时,用主入口导出的 derive

ts
import { derive } from 'vue-amazing-ui'
import type { ThemeVars } from 'vue-amazing-ui'

// 与 <ConfigProvider :theme="{ seed, mode }"> 写出的 42 个变量逐值一致
const vars: ThemeVars = derive({ primary: '#18a058' }, 'dark')
vars['--va-primary-color'] // => '#178b4e'
  • derive(seed?, mode?):seed 为 ThemeSeed(未传的字段取默认值),mode 为已解析的 'light' / 'dark'(缺省 'light');
  • 返回 ThemeVars(42 个 --va-* 的只读快照,键名见上一节清单),ThemeSnapshot 是它的只读别名;结果带缓存,同一组输入返回同一对象;
  • 需要 theme.mode = 'auto' 的语义时,请先在业务侧把 auto 解析成 light / dark 再传入 —— derive 只接受已解析的模式(ResolvedMode);
  • 其它主题出口:DEFAULT_PRIMARY / DEFAULT_SEEDS(默认主色与默认种子)、THEME_VAR_NAMES(变量名清单)、MODE_ATTRIBUTE(data-va-mode 属性名);
  • 旧版 getColorPalettes / getAlphaColor 已移除:色阶与透明度色都改由 derive 的返回值和 --va-* 承担,避免出现两套取色口径。

组件级令牌与整组覆盖 ​

只想改某一个组件时(例如「主色按钮变绿、链接仍是品牌蓝」),用 --va-<组件>-*;下面是完整清单与覆盖约定

  • 与全局令牌一样是继承的 CSS 变量,写在任意祖先选择器上即生效,不需要碰库内部类名;
  • 只覆盖常态会出现「悬停跳回默认色」,请整组覆盖(常态 / 悬停 / 按下);底色类令牌要同时看前景色(如滑动输入条的气泡);
  • 令牌按「高频 + 可覆盖」逐步扩展,不追求组件全覆盖:只有当用户能在自己的选择器上覆盖、且确实有「只改这个组件」的场景时,才会公开;
  • 在线演示:组件令牌覆盖。

本节由 tsx scripts/gen-component-vars-doc.ts 从 components/theme/component-vars.ts 生成,请勿手动修改;生成物需提交(不要加进 .gitignore)。

组件令牌是组件内部颜色变量的公开名字(--va-<组件>-*),也包括把组件主色接到具体皮肤上的桥接令牌。 它们与全局令牌一样是普通的 CSS 自定义属性,直接在选择器里赋值即可,沿 DOM 继承生效; 组件令牌只在消费处带默认值、自身不声明,因此写在任何祖先选择器上都能生效,也不会被组件样式反向压住。

组件级主色的支持范围

当前支持 40 个组件:Alert / AutoComplete / BackTop / Badge / Button / Calendar / Carousel / Cascader / Checkbox / ColorPicker / DatePicker / FloatButton / GradientText / Image / Input / InputNumber / InputSearch / LoadingBar / Menu / Message / Modal / Notification / Pagination / Popconfirm / Progress / Radio / Select / Slider / Spin / Steps / Swiper / Switch / Table / Tabs / Tag / TextScroll / Textarea / TimePicker / Timeline / Upload。 Button / Slider / Menu 通过注册表里的 themeRole 令牌映射;其余组件在样式里消费内部桥变量 --va-cp-<component>-primary-*,配置后会覆盖该组件的全部主色使用点。写错组件名会在编译期报错。

成组覆盖 ​

同一个视觉元素的状态是成组的:只改常态会出现「悬停跳回默认色」,只改底色会出现 「文字不可读」。请整组覆盖,或改用 ConfigProvider.seed 让系统派生整套状态。

css
/* 主色按钮:常态 / 悬停 / 按下 */
.my-zone {
  --va-button-primary-color: #18a058;
  --va-button-primary-color-hover: #36ad6a;
  --va-button-primary-color-active: #0c7a43;
}

/* 危险按钮:只覆盖常态即可,悬停 / 按下默认跟随常态色 */
.my-zone {
  --va-button-danger-color: #d03050;
}

/* 滑动输入条:轨道(已选 / 未选)各两态 */
.my-zone {
  --va-slider-track-color: #18a058;
  --va-slider-track-color-hover: #36ad6a;
  --va-slider-rail-color: #eef1f5;
  --va-slider-rail-color-hover: #e3e8ef;
}

/* 数值气泡:底色与文字色必须成对 */
.my-zone {
  --va-slider-tooltip-bg-color: #ffffff;
  --va-slider-tooltip-color: #333639;
}

变量清单 ​

按钮 Button ​

color 属性会在这一个实例上内联写入 --va-button-primary-color 等令牌(实例级覆盖,优先级最高),因此传了 color 时下面这些令牌对该实例不生效。下拉按钮 DropdownButton 的共享分割线也跟随 --va-button-primary-color-hover / --va-button-danger-color-hover。

其中 --va-button-primary-color / --va-button-primary-color-hover / --va-button-primary-color-active / --va-button-solid-text-color 会跟随 ConfigProvider 的 theme.components.Button.primaryColor 自动派生;其余令牌需要用 CSS 直接覆盖。

主色

名称说明默认值
--va-button-primary-color主按钮底色(常态)var(--va-primary-color)
--va-button-primary-color-hover主按钮底色(悬停)var(--va-primary-color-hover)
--va-button-primary-color-active主按钮底色(按下)var(--va-primary-color-active)

前景色

名称说明默认值
--va-button-solid-text-color实色底上的文字色(primary / danger / reverse 共用)var(--va-text-color-solid)

危险色

名称说明默认值
--va-button-danger-color危险按钮底色(常态)var(--va-error-color)
--va-button-danger-color-hover危险按钮底色(悬停);默认跟随常态色,只覆盖常态色时不会跳回全局红var(--va-button-danger-color, var(--va-error-color))
--va-button-danger-color-active危险按钮底色(按下);默认跟随常态色var(--va-button-danger-color, var(--va-error-color))

滑动输入条 Slider ​

其中 --va-slider-track-color / --va-slider-track-color-hover / --va-slider-handle-shadow-color / --va-slider-handle-shadow-color-hover-focus / --va-slider-dot-color-active 会跟随 ConfigProvider 的 theme.components.Slider.primaryColor 自动派生;其余令牌需要用 CSS 直接覆盖。

已选轨道

名称说明默认值
--va-slider-track-color已选轨道底色(常态)var(--va-primary-border-color)
--va-slider-track-color-hover已选轨道底色(悬停)var(--va-primary-color)

未选轨道

名称说明默认值
--va-slider-rail-color未选轨道底色(常态)var(--va-fill-color-1)
--va-slider-rail-color-hover未选轨道底色(悬停)var(--va-fill-color-2)

滑块

名称说明默认值
--va-slider-handle-color滑块圆点底色var(--va-bg-elevated-color)
--va-slider-handle-shadow-color滑块光环色(常态,常驻 2px)var(--va-primary-border-color)
--va-slider-handle-shadow-color-hover-focus滑块光环色(悬停 / 聚焦,放大到 4px)var(--va-primary-color)

刻度点

名称说明默认值
--va-slider-dot-border-color刻度点描边色(常态)var(--va-border-split-color)
--va-slider-dot-border-color-hover刻度点描边色(悬停)var(--va-fill-color-2)
--va-slider-dot-color-active刻度点描边色(激活态,跟随组件级主色)var(--va-primary-border-color)

数值气泡

名称说明默认值
--va-slider-tooltip-bg-color数值气泡底色var(--va-bg-spotlight-color)
--va-slider-tooltip-color数值气泡文字色;改底色时需同步覆盖,否则浅底白字不可读var(--va-text-color-solid)

导航菜单 Menu ​

下表的「浅色 / 深色」指 theme 属性(独立皮肤),与 data-va-mode 暗色模式无关:浅色皮肤的容器令牌跟随全局令牌派生(暗色模式下自动取暗色值),深色皮肤的三只表面令牌(根列表 / 浮层面板 / 内联子菜单)取品牌色暗底 --va-bg-brand-dark-color / --va-bg-brand-dark-deep-color(主色色相与饱和度、亮度压到 8% / 4.5%,两个模式同值),因此换主题色时深色皮肤同步换色相;是否启用这套皮肤只由 theme 属性决定。三只主色桥令牌由 theme.components.Menu.primaryColor 派生;--va-menu-item-selected-* 的默认值通过它们间接跟随组件主色,直接覆盖选中态令牌仍然优先。组件级 primaryColor 同样驱动深色皮肤的三只表面令牌(按该主色重新派生暗底,优先级高于 seed);直接覆盖令牌依然优先级最高。

其中 --va-menu-primary-color / --va-menu-primary-palette / --va-menu-primary-text-color 会跟随 ConfigProvider 的 theme.components.Menu.primaryColor 自动派生;其余令牌需要用 CSS 直接覆盖。

主色

名称说明默认值
--va-menu-primary-color菜单主色桥:选中项文字 / 深色皮肤选中底 / 水平状态下划线var(--va-primary-color)
--va-menu-primary-palette菜单主色浅底桥:浅色皮肤选中项底色(深色皮肤改用 --va-menu-primary-color)var(--va-primary-bg-color)
--va-menu-primary-text-color菜单主色文字桥:浅色皮肤选中项文字 / 水平菜单下划线var(--va-primary-text-color)

容器

名称说明默认值(浅色皮肤 / 深色皮肤)
--va-menu-background菜单根列表背景;弹出子菜单面板取 --va-menu-popup-background,不受它影响浅色 var(--va-bg-container-color)
深色 var(--va-bg-brand-dark-color, #001529)
--va-menu-popup-background弹出子菜单(浮层面板)背景;深色皮肤取品牌色暗底,与根列表同色浅色 var(--va-bg-elevated-color)
深色 var(--va-bg-brand-dark-color, #001529)
--va-menu-inline-submenu-background内联子菜单(inline 展开的下一级列表)背景;深色皮肤取更深一阶的品牌色暗底浅色 var(--va-fill-color-1)
深色 var(--va-bg-brand-dark-deep-color, #000c17)

选中态

名称说明默认值(浅色皮肤 / 深色皮肤)
--va-menu-item-selected-background选中项(含按下态)底色浅色 var(--va-primary-bg-color)
深色 var(--va-primary-color)
--va-menu-item-selected-color选中项文字色 / 水平菜单下划线色浅色 var(--va-primary-text-color)
深色 #fff

文字滚动 TextScroll ​

容器

名称说明默认值
--va-text-scroll-bg-color滚动区域底色(横 / 纵两个变体共用)var(--va-bg-container-color)
--va-text-scroll-shadow-color滚动区域外围阴影色(横 / 纵两个变体共用)var(--va-border-color)

滚动条 Scrollbar ​

滚动条滑块

名称说明默认值
--va-scrollbar-color滚动条滑块底色(常态)var(--va-text-color-disabled)
--va-scrollbar-color-hover滚动条滑块底色(悬停)var(--va-text-color-3)

表格 Table ​

容器

名称说明默认值
--va-table-bg-color表格容器 / 数据行 / 固定列底色var(--va-bg-container-color)

表头

名称说明默认值
--va-table-header-bg-color表头单元格底色(含排序列表头与固定列表头)var(--va-fill-color-4)

底部

名称说明默认值
--va-table-footer-bg-color表格底部(分页区)底色var(--va-fill-color-4)

边框

名称说明默认值
--va-table-border-color单元格分隔线 / 外边框 / 固定列滚动阴影;另作可排序表头底与可排序行悬停底(改浅会连带变亮这两处底色)var(--va-border-split-color)

卡片 Card ​

容器

名称说明默认值
--va-card-bg-color卡片底色var(--va-bg-container-color)

边框

名称说明默认值
--va-card-border-color卡片外边框与标题分割线var(--va-border-split-color)

警告提示 Alert ​

容器

名称说明默认值
--va-alert-bg-color默认态提示框底色(语义态用 --va-{success,warning,error,info}-* 控制)var(--va-fill-color-1)

边框

名称说明默认值
--va-alert-border-color默认态提示框边框(语义态用 --va-{success,warning,error,info}-border-color 控制)var(--va-border-color)

输入框 Input ​

容器

名称说明默认值
--va-input-bg-color输入框底色(含自动填充背景)var(--va-bg-container-color)

边框

名称说明默认值
--va-input-border-color输入框常态边框(聚焦 / 悬停仍由主色派生)var(--va-border-color)

前景色

名称说明默认值
--va-input-text-color输入文字与光标颜色var(--va-text-color-1)
--va-input-placeholder-color占位符文字颜色var(--va-text-color-disabled)

文本域 Textarea ​

容器

名称说明默认值
--va-textarea-bg-color文本域底色(含自动填充背景)var(--va-bg-container-color)

边框

名称说明默认值
--va-textarea-border-color文本域常态边框(聚焦 / 悬停仍由主色派生)var(--va-border-color)

前景色

名称说明默认值
--va-textarea-text-color输入文字与光标颜色var(--va-text-color-1)
--va-textarea-placeholder-color占位符文字颜色var(--va-text-color-disabled)

模态框 Modal ​

容器

名称说明默认值
--va-modal-bg-color弹窗内容区底色var(--va-bg-elevated-color)

前景色

名称说明默认值
--va-modal-title-color弹窗标题颜色var(--va-text-color-1)
--va-modal-text-color弹窗正文颜色var(--va-text-color-1)

抽屉 Drawer ​

容器

名称说明默认值
--va-drawer-bg-color抽屉面板底色var(--va-bg-elevated-color)

边框

名称说明默认值
--va-drawer-header-border-color抽屉头部与内容区之间的分割线var(--va-border-split-color)
--va-drawer-footer-border-color抽屉底部操作区上方的分割线var(--va-border-split-color)

已知限制 ​

  • Teleport 浮层只转发全局令牌:有生效 seed 时 42 个 --va-* 会随浮层根节点下发 (只配置 theme.components 时只转发组件令牌,避免覆盖宿主用纯 CSS 写在 :root 上的主题), 但你在祖先上手写的 组件令牌不会被带过去。受影响场景:

    • Menu 的弹出型子菜单(mode="horizontal"、inlineCollapsed 收起态)里的 --va-menu-item-selected-*;
    • Notification / Modal / Select 等浮层内的 Scrollbar 的 --va-scrollbar-*。

    需要时请在 <html> 或浮层的承载层上设置。Menu 的 inline 模式、Scrollbar 的非浮层用法不受影响。

  • --va-menu-background 只改根列表背景:弹出面板底色由 --va-menu-popup-background 控制、内联子菜单底色由 --va-menu-inline-submenu-background 控制,需分别覆盖。

  • disabled 态不受组件令牌影响:禁用态统一走中性令牌,这是刻意设计。

  • Button 的 danger 默认为单档:常态 / 悬停 / 按下三态默认同色(历史视觉档位缺失); 已支持只覆盖常态色(悬停 / 按下跟随),但默认状态本身没有档位差。

  • --va-scrollbar-width 是全局运行时变量(页面滚动锁定时由库写入 <html>,供固定定位元素补偿宽度), 不属于组件令牌,也不跟随主题派生。

契约说明 ​

  • 本清单是按需扩展的,不代表组件全覆盖:只有上面列出的组件提供组件级令牌, 其余组件的配色请用全局令牌 / props / 作用域 seed;
  • 组件的其它内部变量(尺寸、层级、按 props 计算的实现细节、Tag 色板、深色皮肤色板等)是私有实现, 不承诺、也不在本节列出;
  • 令牌名在 minor 版本内保持稳定,重命名按 major 处理。

暗色覆盖范围:固定色值 ​

mode="dark" 覆盖所有消费 --va-* 的样式;下列颜色按设计固定,不随明暗切换

  • Tag 的预设色板(pink / red / blue 等 13 色)按模式声明为组件继承变量(--tag-*,组件自有资产,不属于 --va-* 契约):嵌套作用域与带 data-va-mode 的浮层都取最近作用域的值,不再是“暗色页面里永远走暗色板”;
  • Badge / Result 的自定义色板:浅色值固定,暗色另有一套按暗色阶梯重算的覆盖;语义状态(success / processing / error / warning)与 Timeline 的圆点直接取 --va-*,随模式切换;
  • 深色 Sider:本身就是一套独立预设皮肤,改主题不应重定义它;
  • theme="dark" 的 Menu:皮肤仍是一套独立预设(是否启用只由 theme 属性决定,不随 data-va-mode 切换),但三个表面色的默认值由主色派生(--va-bg-brand-dark-color / --va-bg-brand-dark-deep-color),换主色时同步换色相;需要让它跟随明暗模式或与页面容器同色时,把 --va-menu-background / --va-menu-popup-background / --va-menu-inline-submenu-background 分别指向 --va-bg-container-color / --va-bg-elevated-color / --va-fill-color-1;
  • Image 预览与 Video 播放器的固定 chrome(深色底 + 白色图标);
  • 各类中性投影(box-shadow 中的黑色阴影);
  • Watermark 的水印颜色默认取 --va-fill-color-3(随模式变),只有显式传 textStyle.color 时才脱离主题。

自定义 SVG 不要写 fill="var(--va-*)"

SVG 的 presentation attribute(fill / stroke / stop-color)不解析 CSS 变量,写上去会被静默忽略并退回默认色。请写成 style="fill: var(--va-fill-color-2)" 或用 CSS 类绑定,pnpm verify:theme 会对该写法直接报错。

迁移:旧版主题 API ​

旧版 theme.common.primaryColor / theme.Button.primaryColor 已改为 seed / components;abstract 默认值与被移除的工具函数 / 私有变量见下方逐条

diff
- <ConfigProvider :theme="{ common: { primaryColor: '#ff6900' } }">
+ <ConfigProvider :theme="{ seed: { primary: '#ff6900' } }">

- <ConfigProvider :theme="{ Button: { primaryColor: '#18a058' } }">
+ <ConfigProvider :theme="{ components: { Button: { primaryColor: '#18a058' } } }">
  • 组件级主色(theme.Button.primaryColor)改为 theme.components.Button.primaryColor,只覆盖通用主色;更细的部件颜色用组件级令牌或在子树外层包一个 ConfigProvider 换肤;
  • abstract 默认值由 true 改为 false:不写 abstract 时实例会渲染一层包裹元素(tag 可改为 span 等行内元素),主题只作用于自身子树;需要页面级主题(Teleport 浮层、页面链接色)时在最外层显式传 :abstract="true",嵌套层保持默认;
  • 旧版由 JS 注入的 --<组件名>-primary-color 一类主题对象已移除:组件样式改为只消费 --va-*,配置 theme.components 时由 ConfigProvider 在作用域节点写入内部桥变量(实现细节,不需要手工覆盖);曾用这些变量覆盖配色的样式需改为 --va-<组件名>-* 令牌;
  • 需要单独调某个组件的配色时,用 组件级令牌 的 --va-<组件>-*:它是 CSS 侧的公开名(不是旧版由 JS 注入的主题对象),组件私有变量仍不对外承诺;
  • 取色改用主题派生:--va-* 由 ConfigProvider 写入,JS / canvas / SVG 场景用公开的 derive(seed, mode) 取同一份结果;旧版 getColorPalettes / getAlphaColor 已随本版移除;
  • 定时与暗色切换:rafTimeout / cancelRaf 改用 setTimeout / 原生 requestAnimationFrame(返回类型 AnimationFrameID 一并移除),toggleDark 改用 theme.mode,或直接写 <html data-va-mode="dark">;
  • 旧版通过行内变量覆盖组件配色的写法,改为覆盖上表的 --va-*(注意优先级随级联关系变化)。

离散 API:与 createDiscreteApi 的关系 ​

离散实例的浮层挂在 body:传了 configProviderProps.theme 时由边界转发写到浮层根节点;未传时从 <html> 继承主应用主题

它不会改写 <html>,dispose() 也不会误清除主应用写入的变量。configProviderProps.theme(含 seed / mode / components)会作用于该实例自己的浮层(经内部转发通道写到浮层根节点,不污染全局);未传时浮层沿用 <html> 上的主应用主题。

Released under the MIT License.