一个开发期的主题工具:悬浮按钮点开非模态面板,逐 token 编辑库的语义色
(每行一个 ColorPicker 色板加自由文本框)和
--radius 滑杆。改动通过一个文档级 <style> 实时注入,portal 弹层一并跟随;
默认值从已加载样式表的 CSSOM 现读(:root 与 .dark, [data-theme='dark']
两块),组件里没有任何一份会过期的主题副本。
当前编辑亮色还是暗色,跟随 <html> 自己的暗色记号(.dark 类或
data-theme="dark",与 styles.css 认的是同一对)——用 MutationObserver 观察,
不依赖任何主题库。
本站右下角的编辑器就是它(docs layout 挂的全局实例,传了中文文案)。上面这个
demo 是内联摆放的第二个实例:改动同样立即作用于整站,storageKey={null}
让它不与全局实例抢存储。
使用
import { ThemeEditor } from '@gedatou/cadenza-ui'<ThemeEditor />默认 fixed 悬浮在视口右下;根是普通 <div>,用 className 覆盖 inset
工具类换位置,或覆盖 static 改为内联摆放。
历史
撤回/重做维护一条最多 20 步的历史。步的粒度按「连续同源合并」:拖一趟 滑杆、在同一个 token 里打完一串字符是一步;换 token、换操作类型才切新步; 重置和导入是独立步——重置本身可以撤回。新操作会作废重做栈。
导入与导出
「导出 CSS」把亮暗两套完整 token 块(shadcn 约定的 :root {} + .dark {})
下载成一个 CSS 文件(文件名由 exportFileName 定,默认 theme.css);
「导入」解析粘贴的同格式 CSS 并合并进当前改动(只粘三个 token 不会清掉
其他手改)。带 CSS 结构字符的值(red})在注入与导出时整条跳过,防止静默
弄坏整个样式块。
持久化
改动以 storageKey(默认 cadenza-theme-editor)存进 localStorage,挂载时
恢复;清空全部改动即清除存储。传 storageKey={null} 整体关闭持久化——
页面上有第二个实例时(比如本页的 demo)应当关闭,免得两个实例互写同一个 key。
本地化
可见文案全部走平铺的 *Label 字符串 props,默认英文;分组标题跟着 groups
数据走。逐条传译文即可整体换语言:
受控
面板开合支持受控三件套,回调第二参是带 reason(trigger-press /
close-press / escape-key)的事件详情,cancel() 拒掉这次开合:
const [open, setOpen] = useState(false)
<ThemeEditor
open={open}
onOpenChange={(next, details) => {
if (details.reason === 'escape-key')
details.cancel() // 只许按钮关,不许 Esc 关
else
setOpen(next)
}}
/>状态与 className
根是普通 <div>,className 诚实地只收 string,与默认类经 cn 合并
(caller 的赢)。
键盘交互
Props
顺序规则:必填 → 非受控默认值 → 受控值 → 回调 → 行为开关 → 外观 → className。 一体化工具组件,props 面是封闭的(不向任何元素透传)。
4 个类型一并导出:ThemeEditorProps / ThemeEditorGroup /
ThemeEditorOpenChangeEventReason / ThemeEditorOpenChangeEventDetails。