返回目录
组件详情入口
工具
@vean/ui
SThemeCustomizer

ThemeCustomizer

ThemeCustomizer 属于 工具 分类。建议先看演示与用法,再对照 API 表格完成接入和样式调整。

先用快捷跳转面板找到概述、用法、演示和 API,再往下细读完整文档内容。

快速跳转

同分类组件

如果你在同一类交互里做组合,这些组件通常会一起出现。

ThemeCustomizer

概述

SThemeCustomizer 是 Vean 主题引擎的可视化编辑主体:它暴露全部 ThemeOptions 字段以及逐 token 的明暗覆盖,并把每次改动直接写入运行时主题。适合需要提供应用内主题设置面板的场景。

它是一个主体,不是外壳——自身不渲染任何 popover / drawer / sidebar。调用方自行决定挂载位置:设置按钮背后的 SPopover、SDrawer 面板,或内联的侧栏区域。这一拆分是有意为之:面板只负责维持一个稳定的盒子,容器交给宿主决定。

它读写外层 SConfigProvider 持有的主题上下文,因此当宿主还需要紧凑的明暗控件时,可与 SThemeModeSegment / SThemeModeSelect 搭配使用。

用法

特性

  • 🧭 两个顶层标签页——Theme(常规设置)与 Custom(逐 token 覆盖)
  • 🗂 通过 sections 可选八个分区:mode / palette / radius / size / spacing / font / scheme / advanced
  • 🎨 七槽 ui 映射(root / tabs / content / panel / actions)用于外壳覆盖
  • 🧱 稳定的盒子——固定 w-96 h-[70vh],内容区滚动并保留 scrollbar-gutter: stable,切换标签页不会引起宿主 popover 尺寸变化
  • 🌗 mode 由 SThemeModeSegment 承担,因此 auto 走系统解析而非二元开关
  • ✍️ 字体编辑覆盖四条臂(sans / serif / mono / heading),每条可接受预设键或自定义字族栈
  • 🧬 Custom 页按分组平铺约 41 个语义 token,并绑定引擎派生值,因此覆盖项能直接看到当前解析结果
  • ♿ 文案随语言切换,size 转发给全部子控件,面板 axe 零违规
  • ⚡ 高级分组按动画帧逐个挂载,打开 Custom 页不会阻塞首屏

演示

基础

API

Aria 层

1

ThemeCustomizer

7 属性
属性
属性名类型默认值描述
class
ClassValue
—
应用于根元素的额外类名。
ui
Partial<ThemeCustomizerUi>
—
针对组件外壳的按槽位类覆盖。 `ui.root` 承载外框,因此当宿主已对显示区域本身进行约束时, 可省略默认的固定宽度/高度(`w-96 h-[70vh]`)。
sections
ThemeCustomizerSection[]
—
要显示的章节(默认显示全部)。
size
ThemeSize
—
传递给底层控件的大小。
persist
boolean
true
是否将更改保存到存储中。
showActions
boolean
true
是否显示底部操作行(保存预设/重置)。
labelResolver
((key: string) => string)
—
将标签键(章节/组/变体标记)解析为显示字符串。

注意事项

架构与对标差异

维度VeanAnt Design / Element Plus / Mantine
引擎单一主题引擎(@vean/theme)与单一 token 契约,面板直接编辑引擎选项各家主题算法或 CSS 变量预设,面板与自身配置结构耦合
容器SThemeCustomizer 只是主体,不带 popover / drawer / modal 外壳通常把面板内嵌在 modal 或 drawer 组件里
覆盖两层:ThemeOptions 字段 + 逐 token 明暗覆盖,并实时预览派生值色板列表,或独立路由里的原始 JSON / css-var 编辑器
持久化SConfigProvider 是 __VEAN_THEME 信封的唯一写入者,面板自身不写存储持久化交由应用处理
token扁平语义 token 契约;面板的分组(surfaces / fills / hairlines / brand / sidebar / feedback / charts)只是展示层词汇分组与 token 是同一份列表

运行时注意

  • 必须处于 SConfigProvider 内部。 面板读取 useTheme(),没有 provider 提供主题上下文时会抛出(useTheme('ThemeCustomizer'))。
  • persist 目前是空操作。 SConfigProvider 是唯一信封写入者(apply → setThemeState → 派生载荷),面板不自行写 __VEAN_THEME;持久化跟随 provider 的 persistTheme。
  • 没有 modelValue。 面板不是受控表单:改动立即作用于运行时主题,也没有取消操作。
  • sections 是白名单过滤。 未列出的分区不渲染;mode 分区只渲染 SThemeModeSegment,advanced 同时覆盖 token 覆盖页与边框浓度 / 表面样式两行。
  • Custom 页较重。 它会挂载约 41 个 SPalettePicker(每个内含完整 SSelect),因此分组按 requestAnimationFrame 逐个追加——断言要等挂载完成,不要只看第一帧。
  • ui.root 是盒子的逃生舱。 宿主若已限定表面尺寸,应覆盖它以去掉默认的 w-96 h-[70vh]。
  • 字体四臂不负责加载字体。 选择字族只写入 CSS 变量;字体文件加载仍由应用负责。

常见问题

如何只显示部分分区?

传入 sections,例如 :sections="['mode', 'palette', 'radius']"。该数组是白名单,默认为全部八个分区。

如何放进 popover 里?

用你自己的容器包住面板——基础示例使用 SPopover 加一个设置按钮触发器。如果宿主已经限定了表面尺寸,覆盖 ui.root 去掉默认固定宽高。

改动写到哪儿了?

写入外层 SConfigProvider 的实时主题上下文。每次编辑立即提交到运行时并重新发出 provider 的主题事件;持久化由 provider 负责。

面板之外如何放明暗控件?

紧凑开关用 SThemeModeSwitch,需要可选 auto 时用 SThemeModeSelect。二者绑定同一主题上下文,因此与面板的 mode 分区始终同步。

如何自定义重置行为?

showActions 渲染的重置行调用 useThemeSettings().reset。若要自己决定重置目标,隐藏该行(:show-actions="false"),再通过 SConfigProvider / setThemeState 把主题拨回去。

为什么 token 编辑后显示的值与输入不同?

Custom 页把每个 SPalettePicker 绑定到派生值(variants.final)而非原始覆盖项。提交后编辑值是精确的:覆盖项按原样写入,但不在覆盖列表中的值显示的是引擎当前派生结果。

更新日志

版本记录按发布版本分组,便于快速查看这个组件在不同版本里的实际变更。

v0.51.0

2026-10-19

对比版本

修复

声明调色板选择器的依赖项并共享语言环境

范围: theme-customizer作者: soybeanjs查看提交5d4b2

v0.50.0

2026-10-02

对比版本

新功能

稳定化 Shell 并移除变量面板

范围: theme-customizer作者: soybeanjs查看提交78811

新功能

将“模式”下拉菜单替换为“主题模式”选项区

范围: theme-customizer作者: soybeanjs查看提交49748

样式

简化事件处理,并为运行时样式更新添加单元测试

范围: theme-customizer作者: soybeanjs查看提交0a2d3

新功能

将“模式”下拉菜单替换为“主题模式”选项区

范围: theme-customizer作者: soybeanjs查看提交49748

修复

简化事件处理,并为运行时样式更新添加单元测试

范围: theme-customizer作者: soybeanjs查看提交0a2d3

新功能

稳定化 Shell 并移除变量面板

范围: theme-customizer作者: soybeanjs查看提交78811

v0.40.0

2026-09-14

对比版本

文档

将切换按钮的弹出框位置改为底部起始

范围: theme-customizer作者: soybeanfe查看提交db819

v0.30.0

2026-08-20

对比版本

样式

将宽度改为 100

范围: theme-customizer作者: soybeanjs查看提交7a3a7

样式

将宽度改为 100

范围: theme-customizer作者: soybeanjs查看提交7a3a7