diff --git a/.docs/dev-design/2026-04-11-外观设置增强-缩放与主题色.md b/.docs/dev-design/2026-04-11-外观设置增强-缩放与主题色.md new file mode 100644 index 0000000..71c094c --- /dev/null +++ b/.docs/dev-design/2026-04-11-外观设置增强-缩放与主题色.md @@ -0,0 +1,675 @@ +# 外观设置增强: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 `