EasyStarter logoEasyStarter

主题系统

配置 Web 应用的主题预设、亮暗模式与默认主题

主题系统

Web 端基于 shadcn/ui 的 CSS 变量体系,支持亮色 / 暗色模式切换,以及多套预设主题(Preset)。


主题预设(Preset)

所有预设定义在:

apps/web/src/configs/theme-presets.ts

每个预设包含亮色和暗色两套完整的 CSS 变量:

export const themePresets = {
  "modern-minimal": {
    label: "Modern Minimal",
    styles: {
      light: {
        background: "#ffffff",
        foreground: "#333333",
        primary: "#3b82f6",
        // ... 其他变量
      },
      dark: {
        background: "#171717",
        foreground: "#e5e5e5",
        primary: "#3b82f6",
        // ... 其他变量
      },
    },
  },
  // 更多预设...
};

内置预设共 25 套,包括:modern-minimalviolet-bloomt3-chatmocha-mousseamethyst-hazedoom-64kodama-grovecosmic-night 等。


更改默认主题

默认主题取 themePresets 对象中的第一个键。调整 theme-presets.ts 中预设的顺序,将期望的主题移到最前面即可:

apps/web/src/configs/theme-presets.ts
export const themePresets = {
  "violet-bloom": { /* ... */ },   // ← 移到第一位,成为默认主题
  "modern-minimal": { /* ... */ },
  // ...
};

如果所有预设都不存在,则回退到 "modern-minimal"(在 web-config.ts 中定义的 fallbackThemePresetKey)。


新增自定义主题

themePresets 对象中追加新的键值对,填入亮色和暗色两套变量:

apps/web/src/configs/theme-presets.ts
export const themePresets = {
  // 现有预设...
  "my-brand": {
    label: "My Brand",
    styles: {
      light: {
        background: "#fafafa",
        foreground: "#111111",
        primary: "#e11d48",
        // ... 完整变量列表参考现有预设
      },
      dark: {
        background: "#0f0f0f",
        foreground: "#f5f5f5",
        primary: "#fb7185",
        // ...
      },
    },
  },
};

新增后,该主题会自动出现在用户可选的主题列表中。


用户偏好存储

用户在应用内选择的主题偏好会持久化到 localStorage

内容
{AppName}-ui-theme外观模式:light / dark / system
{AppName}-ui-preset当前预设键名,如 "modern-minimal"
{AppName}-ui-preset-styles当前预设的 CSS 变量(用于避免 FOUC)

其中 AppName 来自 packages/app-config 中配置的应用名称。


防闪烁脚本(FOUC)

theme-config.ts 导出了一段内联脚本 themeScript,在页面 HTML <head> 中最早执行,在 React 水合之前就将正确的主题 class 和 CSS 变量应用到 <html> 元素上,避免初次加载时的主题闪烁。