主题化(令牌系统)
OpenHuman 可在运行时完全更换皮肤。颜色和字体由 CSS 变量(“令牌”)驱动,因此一个主题只是这些变量的一组值。此页面是贡献者参考文档,介绍令牌系统。
工作原理
令牌:
app/src/styles/tokens.css将每一种可主题化颜色定义为以空格分隔的 RGB 通道三元组 (例如--surface: 255 255 255;)以及字体角色变量(--font-title/heading/body/mono/serif)。浅色调色板位于:root;深色调色板位于:root.dark.Tailwind 连接:
app/tailwind.config.js通过以下方式将这些令牌暴露为工具类颜色:rgb(var(--token) / <alpha-value>)。<alpha-value>这种形式正是让不透明度修饰符能够正常工作的原因(bg-surface/50,bg-primary-500/10)。因此必须使用通道格式:绝不要将令牌存储为十六进制字符串。运行时应用:
app/src/providers/ThemeProvider.tsx解析当前激活的主题并将其覆盖项写入为内联--token/--font-<role>变量上<html>,并切换.dark来自theme.isDark。主题未覆盖的变量会回退到 tokens.css 的默认值;切换时会移除上一个主题遗留下来的变量。状态:
app/src/store/themeSlice.ts保存activeThemeId以及customThemes。内置预设位于app/src/lib/theme/presets.ts。用户在以下位置编辑主题: 设置 → 主题工作室 (app/src/components/settings/panels/ThemeStudioPanel.tsx).
令牌分类
表面
surface, surface-canvas, surface-muted, surface-subtle, surface-strong, surface-hover, surface-overlay
bg-surface, bg-surface-muted,…
文本
内容, content-secondary, content-muted, content-faint, content-inverted
text-content, text-content-muted,…
边框
line, line-strong, line-subtle
border-line, border-line-strong,…
强调色
primary-*, sage-*, amber-*, coral-* (色阶 50…950)
bg-primary-500, text-coral-600,…(由变量支持、可主题化、名称不变)
字体
font-title, font-heading, font-body, font-mono, font-serif
font-title, font-heading, font-body,…
旧的 --cmd-* 以及 --color-* 变量集只是这些规范令牌的薄别名。不要在其中添加新的颜色。
编写组件
使用语义工具类(
bg-surface,text-content,border-line)来表示中性表面/文本/边框,而不是bg-white dark:bg-neutral-900等。你几乎不需要dark:这些变体,因为 token 会自动为你切换。使用强调色调色板(
primary/sage/amber/coral)用于语义颜色;它们可直接主题化,无需额外工作。避免在
className或内联style中硬编码十六进制,因为那会绕过主题化。
迁移 codemod
scripts/theme-codemod/ 会将已审计的 light dark: Tailwind 配对折叠为语义工具类。默认情况下它是幂等的,并以 dry-run 方式运行:
它只重写相邻配对,且绝不触碰带不透明度后缀的工具类或测试文件。映射表: scripts/theme-codemod/map.mjs.
最后更新于