# 前端样式模块化计划（CSS）

> 目标：在完全还原 `static/old_version_backup/前端备份` 视觉与交互的前提下，于 Vite + Vue 3 体系中重构 `static/style.css`，建立可维护、可组合的样式层。本文对应 `doc/frontend/componentization_plan.md` 的 CSS 版本，为后续拆分提供路径、里程碑与验证清单。

## 当前样式现状

1. **单文件真值**：`static/style.css` 仍是唯一的设计源，`static/src/main.ts` 通过 `import '../style.css';` 全局注入。内部含重置、变量、布局、组件、动画等所有样式，尚未按模块切分。
2. **变量体系**：顶层 `:root` 暴露 `--claude-*`（背景、阴影、按钮态等）并在所有组件复用，局部还混用硬编码色值，需要梳理。
3. **全局依赖**：
   - DOM 结构来自 `static/src/App.vue` 及其子组件（`ConversationSidebar.vue`、`LeftPanel.vue`、`ChatArea.vue`、`InputComposer.vue`、`RightFocusPanel.vue` 等）。
   - `AppShell` 提供 Toast/Confirm/EasterEgg/ContextMenu，需要共享阴影与层级变量。
   - 彩蛋 CSS（`static/easter-eggs/*.css`）仍单独引入，迁移不可破坏其优先级。

## 当前状态（2025‑11）

- `static/src/styles/` 已完成 base/layout/components/utilities 分层；`main.ts` 仅导入 `./styles/index.scss`。
- `static/style.css` 不再存放样式，而是 `@import '/static/dist/assets/main.css'`，用于兼容历史入口（终端、登录等仍引用该路径）。
- 旧版 CSS 原样保存于 `static/old_version_backup/前端备份/style.css`，便于对比 legacy 视觉。

## 拆分层级设计

```
static/src/styles/
├── base/          # 重置、字体、变量、icon 工具
├── layout/        # AppShell、主容器、面板栅格
├── components/    # 聊天/输入/侧栏/抽屉等模块
├── utilities/     # 动画、遮罩、z-index、辅助类
└── index.scss     # 汇总入口，由 main.ts 引入
```

- **Base Layer**：`_reset.scss`、`_tokens.scss`、`_global.scss`。负责 `* { box-sizing }`、`:root` 变量、`body` 字体/背景、`.icon` 工具类等；对应当前 `style.css` 前 ~200 行。
- **Layout Layer**：`_app-shell.scss`、`_panels.scss`。控制 `.main-container`、`.conversation-sidebar`、`.sidebar-panel-card`、`.chat-container`、`.right-sidebar` 的尺寸、flex 行为与响应式断点。
- **Component Layer**：按照业务域划分子目录，例如：
  - `components/sidebar/`：历史列表、折叠按钮、搜索框、个人空间入口。
  - `components/panels/`：文件树/TODO/子智能体、TokenDrawer、ResourceStats。
  - `components/chat/`：`ChatArea` + 各 `ActionBlock`、`Thinking` 动画、`copy-code-btn`。
  - `components/input/`：`InputComposer`、`QuickMenu`、工具禁用菜单、设置子菜单。
  - `components/overlays/`：Toast、Confirm、Quota Toast、ContextMenu、Personalization Drawer。
- **Utilities Layer**：抽象 `@keyframes`、`transition` 变量、`.is-hidden`、`.scrollbar`、`.sr-only` 等工具类，避免每个组件重复指定。

## 模块映射（示例）

| 模块文件 | 覆盖区域 | 对应组件/Store | 说明 |
| --- | --- | --- | --- |
| `base/_tokens.scss` | `:root` 变量、阴影、字体 | 全局 | 拆出颜色/阴影/spacing map，供 `@use` 复用，可额外导出 SCSS map 方便组件使用。 |
| `layout/_app-shell.scss` | `.main-container`、`AppShell` slot | `App.vue`, `AppShell.vue` | 负责 viewport 高度、自适应 inset、安全区 padding，保留 `--app-viewport`。 |
| `layout/_sidebar.scss` | `.conversation-sidebar` ~ `.conversation-list` | `ConversationSidebar.vue`, `useConversationStore` | 保留展开/折叠两套宽度，抽象 `@mixin sidebar-button($size)` 简化按钮样式。 |
| `components/chat/_message-list.scss` | `.chat-area`、`.message-item` | `ChatArea.vue` 子组件、`useChatStore` | 细分 Thinking/Text/Tool/Summary 的背景、边框、动画。 |
| `components/input/_composer.scss` | `.compact-input-area` | `InputComposer.vue`, `useInputStore` | 控制多行自动高度、`.action-buttons`、`.quick-menu`。 |
| `components/panels/_token-drawer.scss` | `.token-drawer`, `.usage-stat` | `TokenDrawer.vue`, `useResourceStore` | 与 `legacy_ui_spec` 的折叠动画、进度条变量保持一致。 |
| `components/overlays/_toast.scss` | `.toast-stack`, `.quota-toast` | `ToastStack.vue`, `QuotaToast.vue`, `useUiStore` | 拆分常规 Toast 与 quota 警告两种配色。 |
| `components/overlays/_personalization.scss` | `.personal-page-overlay` | `PersonalizationDrawer.vue`, `usePersonalizationStore` | Drawer 背景、拖拽 handle、Preset 卡片。 |

> 拆分时以 `legacy_ui_spec.md` + `static/style.css` 为真值，逐块复制到对应模块后，再删除旧片段，确保 diff 清晰。

## 迁移阶段

### 阶段 0：建立骨架（已完成）

1. 新建 `static/src/styles/index.scss`，依次 `@use`/`@import` 四层目录。
2. 在 `static/src/main.ts` 将 `import '../style.css'` 替换为 `import './styles/index.scss';`，暂留旧 `style.css` 以供对照。
3. 引入 PostCSS/Sass 配置（若尚未启用 SCSS，可先 `npm install -D sass` 并在 Vite 中开启预处理）。

### 阶段 1：迁移 Base + Layout（已完成）

1. 复制 `style.css` 中 reset/变量/body/header/main-container 相关片段到 base/layout 模块；`style.css` 里保留注释提示“已迁移”。
2. 验证 viewport 高度、侧栏折叠、主容器滚动与之前一致。
3. 为 CSS 变量补充 SCSS map（例如 `$colors: ( 'bg': var(--claude-bg), ... )`），方便组件层调用。

### 阶段 2：侧栏/面板组件（已完成）

1. 以对话侧栏为起点，迁移 `.conversation-sidebar`、`.conversation-header`、`.conversation-list` 等块。
2. 按 `LeftPanel` 面板切换结构拆出 `.sidebar-panel-card`、`.panel-switcher`、`.file-tree`、`.todo-panel`、`.subagent-panel`。
3. 将 hover/active/disabled 态封装混入，消除硬编码颜色。

### 阶段 3：聊天 + 输入域（已完成）

1. 拆分 `.chat-container`、`.chat-scroll`、`.message-item` 及各 action（thinking/text/tool/append/modify/system）的背景、边框、状态类（`.is-streaming`, `.is-collapsed`）。
2. 将 `.compact-input-area`、`.input-actions`、`.quick-menu`、`.tool-settings-menu` 拆到 `input/` 目录，保留动画 `@keyframes submenu-slide`。
3. Chat/Input 共用的 `code` 块、`.copy-code-btn`、`.token-counter` 等交叉样式放在 utilities 或共享 partial。

### 阶段 4：Overlay/Drawer & 清理（已完成）

1. 迁移 ToastStack、QuotaToast、ConfirmDialog、ContextMenu、Personalization Drawer、EasterEgg overlay 的样式，集中管理 z-index、backdrop-filter。
2. 为 `FocusPanel`、`TokenDrawer`、`UsageDashboard` 等右栏模块建立专属文件。
3. 将 `static/style.css` 改为 `@import '/static/dist/assets/main.css'`，对外暴露单一入口，同时在 `static/old_version_backup/前端备份/style.css` 保留 legacy 真值以便比对。

## 验证清单

1. `npm run build`、`npm run dev` 均可正常注入 SCSS，无额外 CSS 顺序冲突。
2. 浏览器端逐项对照 `doc/frontend/legacy_ui_spec.md`：
   - 侧栏展开/折叠宽度 & hover 状态。
   - 三合一 Panel 切换 & 文件树/右键菜单层级。
   - 聊天消息块的动效（思考流式、压缩动画、复制按钮）。
   - Quick Menu 子菜单、工具禁用对话框、设置二级菜单。
   - Toast/Quota 警告淡入淡出、个人空间 Drawer 背景模糊。
3. 对彩蛋 CSS（`static/easter-eggs/*.css`）做回归，确保 `AppShell` overlay 的 stacking context 不影响其覆盖。

## 后续维护建议

1. **新模块接入**：新增组件请优先在 `static/src/styles/components/` 下创建局部 SCSS，再通过 `styles/index.scss` 聚合，避免回落到全局样式。
2. **主题扩展**：如需暗色/高对比主题，可在 `base/_tokens.scss` 内维护多套 map，并通过 `@mixin` 输出 CSS variables。
3. **旧入口兼容**：登录/终端等仍引用 `/static/style.css`，更新后务必同步 `npm run build` 以生成最新 `dist/assets/main.css`，否则旧入口将缺少样式。
4. **快照对比**：大规模改动前可先复制 `static/old_version_backup/前端备份/style.css` 为参考，再利用浏览器 devtools 对比差异，降低视觉回归风险。

## 注意事项

- **优先级控制**：使用 `@layer base|layout|components|utilities`（Vite 支持原生 CSS Layers）保证与旧版 specificity 相匹配，避免引入 `!important`。
- **变量延续**：保留 `--app-viewport`、`--app-bottom-inset` 等运行时变量，store/composable 仍通过 `document.documentElement.style` 更新这些值。
- **资源路径**：`mask-image`、背景图标继续指向 `/static/icons/*`，拆分后请集中在 `base/_icon.scss` 管理。
- **主题扩展**：如需暗色或高对比方案，可在 `_tokens.scss` 中提供多套 map，使用 `data-theme` 切换；现阶段仅实现 legacy 主题。
- **发布节奏**：每完成一个层级都应在 PR 中附对比截图（侧栏、聊天、输入、Overlay），并同步更新本文件进度记录。

> 完成上述阶段后，CSS 将具备与组件结构一致的模块边界，便于日后按需维护、替换或添加主题，同时保持 `legacy` 品牌体验不变。
