# 外观设置增强:Window Zoom Level 与 Theme Color 预设 | 字段 | 值 | | ---------- | ------------------------------------------ | | 创建日期 | 2026-04-11 | | 作者 | xintaofei | | 关联 Issue | TBD | | 类型 | 开发详细设计(Dev Design) | | 状态 | Draft | ## 1. 背景与目标 ### 1.1 背景 当前 `设置 / 外观` 页面 (`src/components/settings/appearance-settings.tsx`) 只有一个"主题模式"选择器(`system / light / dark`,由 `next-themes` 驱动)。项目已经使用 Tailwind CSS v4 + shadcn/ui(OKLch 色彩)做基础主题,但用户无法调整: - **UI 整体缩放**(类似 VSCode `Window: Zoom Level`)——不同分辨率 / 视力偏好下需要整体放大或缩小界面 - **主题强调色**(shadcn 官方提供 12 个预设:Zinc / Slate / Stone / Gray / Neutral / Red / Rose / Orange / Green / Blue / Yellow / Violet) ### 1.2 目标 1. 在 `设置 / 外观` 页面新增两个偏好项:**Window Zoom** 和 **Theme Color** 2. 参考 [shadcn/ui Theming 文档](https://ui.shadcn.com/docs/theming) 的做法,提供 12 个官方主题预设,切换后 primary / accent / ring / border 等所有 shadcn CSS 变量联动更新 3. 保持与现有 `next-themes` 的 light/dark 切换**完全正交**——用户可以在 `Blue` 主题下自由切换浅色/深色 4. 首次加载无闪烁(FOUC),刷新后保持用户选择 5. 提供"恢复默认"按钮 ### 1.3 非目标 - **不跨设备同步**:两个新增偏好均存于浏览器 `localStorage`,每台设备/每个浏览器独立(符合"缩放本就是设备属性"的直觉) - **不自定义具体颜色值**:只支持 12 个预设,不开放 color picker 或自定义面板 - **不影响 Monaco 编辑器 / 终端等排印学专属字号**:本次缩放只作用于 UI 层,代码编辑器保持独立字号 - **不改动后端**:零后端代码改动,无需新增 API 或数据库字段 ## 2. 需求确认摘要 | 决策点 | 选择 | | -------------------- | ---------------------------------------------------------------------------------------------- | | 缩放作用范围 | 全局窗口缩放(调 `html { font-size }`,所有 rem 连锁) | | 缩放档位与交互 | 离散百分比 + shadcn `Select`:`80% / 90% / 100% / 110% / 125% / 150%`,默认 100%,无快捷键 | | 主题色定制粒度 | 预设主题色盘(12 个 shadcn 官方预设,每个包含 light + dark 两套变量),默认 Zinc | | 持久化层 | 全部 `localStorage`,每设备独立,不走后端 | | 预设主题列表 | 12 个 shadcn 标准预设(Zinc / Slate / Stone / Gray / Neutral / Red / Rose / Orange / Green / Blue / Yellow / Violet) | | Provider 嵌套顺序 | `` (外) → `` (内) | | 跨标签页同步 | 开启(`storage` 事件监听) | | Hook 拆分 | `useAppearance` + `useThemeColor` + `useZoomLevel` | | Theme Color UI | 按钮网格(响应式 3/4/6 列),非下拉 | | 色盘圆点代表色 | 硬编码在 `theme-presets.ts` 的 `THEME_COLOR_PREVIEW`,和 `globals.css` 双写但数据可控 | | 卡片布局 | 三张卡片堆叠在同一个 `/settings/appearance` 页面,不拆子路由 | | 重置按钮范围 | 只重置 Theme Color 和 Zoom,不动 Theme Mode | | 重置按钮位置与样式 | 页面底部右侧,`variant="outline"` + `size="sm"`,`RotateCcw` 图标,默认值时 disabled,无确认框 | ## 3. 整体架构与数据流 ### 3.1 三条正交的运行时状态 | 偏好项 | localStorage key | DOM 写入位置 | 变更来源 | | ----------- | --------------------- | ----------------------------------- | --------------------------------- | | Theme Mode | `theme`(next-themes)| `` | 既有 `next-themes`,本次不动 | | Theme Color | `codeg-theme-color` | `` | 新增 `useThemeColor()` | | Zoom Level | `codeg-zoom-level` | `` | 新增 `useZoomLevel()` | 三者完全独立读写,互不干扰。`.dark` 类和 `[data-theme="xxx"]` 属性在 CSS 层叠中是两个正交维度。 ### 3.2 数据流示例:用户点选 "Blue" 主题色 ``` 用户点击 Blue 按钮 ↓ useThemeColor().setThemeColor("blue") ↓ ① localStorage.setItem("codeg-theme-color", "blue") ② document.documentElement.setAttribute("data-theme", "blue") ↓ CSS 中 [data-theme="blue"] { --primary: ...; ... } 命中 所有使用 --primary / --accent / --ring / --border 的 Tailwind 类立即重算 ↓ Monaco 编辑器的 useMonacoThemeSync(监听 .dark class)不会误触发 ``` ### 3.3 首次加载 / 硬刷新的防闪烁 在 `` 顶部注入同步执行的 inline `