Skip to content

主题定制

ZC UI 提供完整的运行时主题定制能力,包括:品牌色动态切换、主题预设系统、组件级主题覆写、CSS 变量命名空间、CSS Layer 优先级控制,以及主题色阶生成工具。

概览

mermaid
graph LR
  A[品牌色输入] --> B[色阶生成器]
  B --> C[主题预设 Preset]
  C --> D[运行时 API]
  D --> E[CSS 变量]
  E --> F[组件渲染]
  G[ConfigProvider] --> D
  H[命名空间] --> E

运行时品牌色切换

通过 setBrandColor()setBrandColors() 在运行时动态切换品牌色,自动生成完整的 50–950 色阶。

基本用法

ts
import { setBrandColor, setBrandColors } from '@zc-ui/theme'

// 切换单个品牌色
setBrandColor('primary', '#722ed1')

// 切换多个品牌色
setBrandColors({
  primary: '#722ed1',
  success: '#52c41a',
  danger: '#ff4d4f',
})

通过 ConfigProvider 切换

选择主题色:

主题预设系统

类似 Naive UI 的 darkTheme / lightTheme,ZC UI 提供内置主题预设,并支持自定义创建。

内置预设

ts
import { lightTheme, darkTheme } from '@zc-ui/theme'

// 当前预设的变量
console.log(lightTheme.variables['--color-zc-primary-500']) // '#409eff'
console.log(darkTheme.variables['--color-zc-bg-base'])      // '#1d1d1d'

创建自定义预设

ts
import { createTheme, mergeThemes, darkTheme } from '@zc-ui/theme'

// 基于品牌色创建
const brandTheme = createTheme({
  name: 'purple-brand',
  brandColors: { primary: '#722ed1' },
  componentOverrides: {
    Button: {
      '--zc-button-border-radius': '8px',
      '--zc-button-font-weight': '600',
    },
  },
})

// 合并预设(后者覆盖前者)
const purpleDark = mergeThemes(darkTheme, brandTheme)

预设注册与切换

ts
import { registerTheme, switchTheme, createTheme } from '@zc-ui/theme'

// 注册多个主题
registerTheme('brand', createTheme({ brandColors: { primary: '#722ed1' } }))
registerTheme('dark', darkTheme)
registerTheme('light', lightTheme)

// 按名称切换
switchTheme('brand')
switchTheme('dark')

应用预设

ts
import { applyTheme, darkTheme } from '@zc-ui/theme'

// 应用到 document
applyTheme(darkTheme)

// 应用到指定元素
const el = document.querySelector('.my-section')
applyTheme(darkTheme, { target: el })

组件级主题覆写 (themeOverrides)

通过 ConfigProvider 的 themeOverrides 属性,可以按组件粒度覆盖 CSS 变量。

直角标签

完整示例

vue
<template>
  <ZcConfigProvider
    :brand-colors="{ primary: '#722ed1' }"
    :theme-variables="{ '--radius-zc-base': '10px' }"
    :theme-overrides="{
      Button: { '--zc-button-font-weight': '700' },
      Input: { '--zc-input-border-color': '#d9d9d9' },
      Card: { '--zc-card-shadow': '0 4px 12px rgba(0,0,0,0.1)' },
    }"
  >
    <App />
  </ZcConfigProvider>
</template>

CSS 变量命名空间

支持多套 CSS 变量前缀并存,适用于白标应用或多品牌场景。

ts
import { createNamespace, applyNamespace } from '@zc-ui/theme'

// 创建命名空间
const ns1 = createNamespace('brand-a', {
  brandColors: { primary: '#722ed1' },
})
const ns2 = createNamespace('brand-b', {
  brandColors: { primary: '#00b96b' },
})

// 应用到不同区域
applyNamespace(document.querySelector('.section-a'), ns1)
applyNamespace(document.querySelector('.section-b'), ns2)

在 CSS 中使用命名空间变量:

css
.section-a .my-button {
  background: var(--color-brand-a-primary-500);
}

.section-b .my-button {
  background: var(--color-brand-b-primary-500);
}

CSS Layer 支持

ZC UI 使用 CSS @layer 控制样式优先级,避免样式冲突。

层级顺序(从低到高)

层级说明
zc-resetCSS 重置样式
zc-tokens设计令牌(CSS 变量定义)
zc-base基础元素样式
zc-components组件样式
zc-overrides用户/运行时主题覆写(最高优先级)

在自定义样式中使用

css
/* 你的覆写样式放入 zc-overrides 层,自动获得最高优先级 */
@layer zc-overrides {
  .my-custom-button {
    background: var(--color-zc-primary-500);
  }
}

编程方式

ts
import { wrapInLayer, cssLayerDeclaration } from '@zc-ui/theme'

const myCss = wrapInLayer('zc-overrides', `
  .my-button { border-radius: 8px; }
`)

主题色阶生成工具

输入单个品牌色,自动生成完整的 50–950 色阶。

ts
import { generateColorScale, generatePalette } from '@zc-ui/theme'

// 生成单个色阶
const scale = generateColorScale('#722ed1')
// {
//   50: '#f9f0ff',
//   100: '#efdbff',
//   ...
//   500: '#722ed1',
//   ...
//   950: '#220938'
// }

// 生成完整调色板
const palette = generatePalette({
  primary: '#722ed1',
  success: '#52c41a',
  danger: '#ff4d4f',
})

色阶生成 CSS 变量

ts
import { generatePalette, paletteToCssVars, paletteToCssText } from '@zc-ui/theme'

const palette = generatePalette({ primary: '#722ed1' })

// 转为 CSS 变量对象
const vars = paletteToCssVars(palette)
// { '--color-zc-primary-50': '#f9f0ff', ... }

// 转为 CSS 文本
const css = paletteToCssText(palette, ':root')
// :root { --color-zc-primary-50: #f9f0ff; ... }

暗色模式

ts
import { applyTheme, darkTheme, lightTheme, applyDarkMode } from '@zc-ui/theme'

// 方法 1:使用预设
applyTheme(darkTheme)
applyTheme(lightTheme)

// 方法 2:直接切换 class
applyDarkMode(true)   // 添加 .dark 类
applyDarkMode(false)  // 移除 .dark 类

// 方法 3:通过 useDark 组合式函数
import { useDark } from '@zc-ui/hooks'
const { isDark, toggle } = useDark()

主题控制器 (Theme Controller)

ts
import { createThemeController, darkTheme } from '@zc-ui/theme'

const controller = createThemeController()

controller.apply(darkTheme)                 // 应用预设
controller.setBrandColor('primary', '#722ed1') // 切换品牌色
controller.setVariable('--my-var', '20px')  // 设置 CSS 变量
controller.toggleDark()                     // 切换暗色模式
controller.clear()                          // 清除所有运行时覆写

API 参考

运行时 API

函数说明
applyTheme(preset, options?)应用完整主题预设
setBrandColor(name, hex, options?)设置单个品牌色
setBrandColors(palette, options?)设置多个品牌色
setThemeVariable(name, value, options?)设置单个 CSS 变量
removeThemeVariable(name, options?)移除 CSS 变量
applyDarkMode(isDark, target?)切换暗色模式
clearThemeOverrides(options?)清除所有运行时覆写
registerTheme(name, preset)注册命名主题
switchTheme(name, options?)切换到已注册主题
createThemeController(options?)创建主题控制器

主题预设 API

函数说明
createTheme(options)创建自定义主题预设
mergeThemes(...presets)合并多个预设
getComponentOverrides(theme, name)获取组件覆写
themeToCssText(theme, selector?)预设转 CSS 文本

色阶生成 API

函数说明
generateColorScale(hex)生成 50–950 色阶
generatePalette(input)生成完整调色板
paletteToCssVars(palette, prefix?)转为 CSS 变量对象
paletteToCssText(palette, selector?)转为 CSS 文本
getContrastRatio(hex1, hex2)计算对比度
getReadableTextColor(bgHex)获取最佳文字颜色

命名空间 API

函数说明
createNamespace(name, options)创建命名空间
applyNamespace(element, ns)应用命名空间到元素
removeNamespace(element, ns)移除命名空间
createVarResolver(name)创建变量名解析器

基于 MIT 许可发布