@hzab/theme-tools
v0.0.3
Published
主题切换配置
Readme
theme-tools 主题切换插件
一个 React 主题切换解决方案,支持动态主题配置、自动暗色模式、CSS 变量管理和类型安全的主题开发。
✨ 特性
| 功能 | 描述 |
|---------------------|--------------------------------------------------------------------|
| 🌈 多模式支持 | 亮色/暗色/自动/自定义主题模式以及动态型自定义主题模式 |
| 🤖 自动暗色适配 | 智能跟随系统主题变化 |
| 🎨 CSS 变量管理 | 自动转换驼峰命名到 CSS 变量格式 (e.g. primaryColor → --primary-color) |
| 🧩 插件化架构 | 轻松扩展自定义主题配置 |
| 🚀 高性能 | 基于 Emotion CSS-in-JS 和智能缓存优化 |
| 🔒 类型安全 | 完整的 TypeScript 类型支持 |
⬇️ 安装
npm install @hzab/theme-tools
# 或
yarn add @hzab/theme-tools📚 核心功能
主题模式
- light: 强制亮色模式
- dark: 强制暗色模式
- auto: 自动匹配系统主题
- custom: 动态型自定义主题
- 扩展模式:支持通过配置添加任意主题模式
CSS 变量管理
自动将主题配置转换为 CSS 变量,将小驼峰的变量转为符合CSS变量规范的中划线格式,例如primaryColor会被转换为--primary-color ```css
:root {
--primary-color: #1677ff;
--text-color: rgba(0, 0, 0, 0.88);
}
```主题配置
主题优先级从高到低:overrides > customModes > defaultModes, overrides属性属于修复型配置
📚 API 参考
ThemeProvider
| 属性 | 类型 | 默认值 | 描述 | 版本 | |--------------|-----------------------------------------------------|----------------|---------------------------------|-------| | appearance | "light" | "dark" | "custom" | "auto" | "string" | "light" | 外观 | 0.0.1 | | themeConfig | ThemeConfig | - | 主题配置对象 | 0.0.1 | | prefix | string | - | CSS变量前缀 | 0.0.1 | | hashPriority | "low" | "high" | "high" | 插入样式时是否降低选择器优先级 | 0.0.1 | | cssVarMountName | string | ":root" & body | 自定义CSS变量挂载位置,指为css选择器,选择器名称尽量唯一 | 0.0.3 |
useTheme
const { token, css, cx } = useTheme()useThemeMode
// 控制主题模式
const {
themeMode,
appearance,
setThemeMode,
availableModes,
isDarkMode,
// ...更多其它属性
}: ThemeContextState = useThemeMode()Type
ThemeProviderProps
interface ThemeProviderProps {
/**
* @title 变量前缀
*/
prefix?: string;
/**
* @title 默认主题模式
* @default "light"
*/
appearance?: ThemeMode;
/**
* @title 主题配置
*/
themeConfig?: ThemeConfig;
/**
* @title 使用emtion时是否开启优先级降低模式(在开发组件时比较有用,可以更简单的覆盖组件样式)
*/
hashPriority?: HashPriority;
/**
* @title 自定义挂载css变量节点的位置,值为id选择器或者class选择器,名称尽可能的唯一
*/
cssVarMountName?: string;
children?: React.ReactNode;
}
ThemeConfig
type ThemeConfig<T = Record<string, any>> = {
/**
* @title 默认主题配置
*/
defaultModes?: ThemeConfigDefaultType<T>;
/**
* @title 自定义主题模式
*/
customModes?: Record<string, Partial<T>>;
/**
* @title 全局覆盖(紧急修复用)
* @description 会覆盖所有模式的配置,慎用
*/
overrides?: Partial<T>;
};
ThemeContextState
interface ThemeContextState<T = Record<string, any>> {
/**
* @title 当前主题配置
*/
token: T;
/**
* @title 外观
*/
appearance: ThemeAppearance;
/**
* @title 主题模式
* @enum ["light", "dark", "custom", "auto", [key: string]: Record<string, string> ]
* @enumNames ["亮色模式", "暗色模式", "跟随系统", "动态型自定义","配置型自定义"]
* @default "light"
*/
themeMode: ThemeMode;
/**
* @title 是否是暗色主题
*/
isDarkMode: boolean;
/**
* @title 主题模式集合
*/
availableModes?: Array<keyof ThemeConfigDefaultType & T>;
/**
* @title EmotionCache
*/
cache: EmotionCache;
/**
* @title 设置主题模式
*/
setThemeMode: (themeMode: ThemeMode) => void;
/**
* @title 设置自定义主题模式
*/
setCustomToken: (token: T) => void;
/**
* @title 重置自定义主题
*/
resetCustomToken: () => void;
/**
* @title 缓存实例
*/
cacheManager: CacheManager;
}
🎯 最佳实践
支持三种使用方式,建议使用第一种
- themeConfig中的配置会转换为body节点上的全局css变量,因此在使用时直接使用相关css变量即可;
- 支持自定义挂载节点配置,将变量挂载到某个id选择器或者class选择器下面,默认挂载位置是“:root”和body;
- 通过自定义hooks可以拿到相关的token配置;
- Emotion CSS-in-JS 的写法:通过createStyles函数创建样式对象,返回一个自定义hook,该hook包函样式对象属性,通过className的方式引用样式对象即可;
基础使用
import { ThemeProvider, useTheme } from '@hzab/theme-switch'
function App() {
return (
<ThemeProvider
appearance="auto"
themeConfig={{
defaultModes: {
light: { primary: '#1677ff', text: '#000' },
dark: { primary: '#1890ff', text: '#fff' }
}
}}
>
<MyComponent />
</ThemeProvider>
)
}
使用方式1:
// 在组件中
function MyComponent() {
const { token } = useTheme()
return (
<div style={{ color: token.text }}>
<button style={{ background: token.primary }}>
主题化按钮
</button>
</div>
)
}
使用方式2:
.container {
width: 100vw;
height: 100vh;
background-color: var(--background-color);
}进阶用法
通过useThemeMode实现模式切换
// 创建带自动 CSS 变量转换的样式
const useStyles = createStyles(({ token, css }) => ({
container: css`
background: token.background;
padding: 16px;
border: 1px solid ${token.border};
&:hover {
background: ${token.primary}20;
}
`
}))
// 切换主题模式
function ThemeSwitcher() {
const { themeMode, setThemeMode } = useThemeMode()
return (
<div>
<button onClick={() => setThemeMode('light')}>亮色</button>
<button onClick={() => setThemeMode('dark')}>暗色</button>
<button onClick={() => setThemeMode('custom')}>自定义</button>
</div>
)
}📌 注意事项
React ≥ 16.8 (需要 Hooks)
TypeScript ≥ 4.1 (推荐)
推荐使用防抖/节流处理主题更新操作
避免在渲染循环中频繁调用 setCustomToken(),由于是Emotion CSS-in-JS的动态方案,在每次调整主题样式相关的状态时都会插入一个style标签,在大量更新(例如使用调色板)主题状态时,会插入非常多的style标签会
