9.2 KiB
9.2 KiB
前端样式模块化计划(CSS)
目标:在完全还原
static/old_version_backup/前端备份视觉与交互的前提下,于 Vite + Vue 3 体系中重构static/style.css,建立可维护、可组合的样式层。本文对应doc/frontend/componentization_plan.md的 CSS 版本,为后续拆分提供路径、里程碑与验证清单。
当前样式现状
- 单文件真值:
static/style.css仍是唯一的设计源,static/src/main.ts通过import '../style.css';全局注入。内部含重置、变量、布局、组件、动画等所有样式,尚未按模块切分。 - 变量体系:顶层
:root暴露--claude-*(背景、阴影、按钮态等)并在所有组件复用,局部还混用硬编码色值,需要梳理。 - 全局依赖:
- 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)仍单独引入,迁移不可破坏其优先级。
- DOM 结构来自
当前状态(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:建立骨架(已完成)
- 新建
static/src/styles/index.scss,依次@use/@import四层目录。 - 在
static/src/main.ts将import '../style.css'替换为import './styles/index.scss';,暂留旧style.css以供对照。 - 引入 PostCSS/Sass 配置(若尚未启用 SCSS,可先
npm install -D sass并在 Vite 中开启预处理)。
阶段 1:迁移 Base + Layout(已完成)
- 复制
style.css中 reset/变量/body/header/main-container 相关片段到 base/layout 模块;style.css里保留注释提示“已迁移”。 - 验证 viewport 高度、侧栏折叠、主容器滚动与之前一致。
- 为 CSS 变量补充 SCSS map(例如
$colors: ( 'bg': var(--claude-bg), ... )),方便组件层调用。
阶段 2:侧栏/面板组件(已完成)
- 以对话侧栏为起点,迁移
.conversation-sidebar、.conversation-header、.conversation-list等块。 - 按
LeftPanel面板切换结构拆出.sidebar-panel-card、.panel-switcher、.file-tree、.todo-panel、.subagent-panel。 - 将 hover/active/disabled 态封装混入,消除硬编码颜色。
阶段 3:聊天 + 输入域(已完成)
- 拆分
.chat-container、.chat-scroll、.message-item及各 action(thinking/text/tool/append/modify/system)的背景、边框、状态类(.is-streaming,.is-collapsed)。 - 将
.compact-input-area、.input-actions、.quick-menu、.tool-settings-menu拆到input/目录,保留动画@keyframes submenu-slide。 - Chat/Input 共用的
code块、.copy-code-btn、.token-counter等交叉样式放在 utilities 或共享 partial。
阶段 4:Overlay/Drawer & 清理(已完成)
- 迁移 ToastStack、QuotaToast、ConfirmDialog、ContextMenu、Personalization Drawer、EasterEgg overlay 的样式,集中管理 z-index、backdrop-filter。
- 为
FocusPanel、TokenDrawer、UsageDashboard等右栏模块建立专属文件。 - 将
static/style.css改为@import '/static/dist/assets/main.css',对外暴露单一入口,同时在static/old_version_backup/前端备份/style.css保留 legacy 真值以便比对。
验证清单
npm run build、npm run dev均可正常注入 SCSS,无额外 CSS 顺序冲突。- 浏览器端逐项对照
doc/frontend/legacy_ui_spec.md:- 侧栏展开/折叠宽度 & hover 状态。
- 三合一 Panel 切换 & 文件树/右键菜单层级。
- 聊天消息块的动效(思考流式、压缩动画、复制按钮)。
- Quick Menu 子菜单、工具禁用对话框、设置二级菜单。
- Toast/Quota 警告淡入淡出、个人空间 Drawer 背景模糊。
- 对彩蛋 CSS(
static/easter-eggs/*.css)做回归,确保AppShelloverlay 的 stacking context 不影响其覆盖。
后续维护建议
- 新模块接入:新增组件请优先在
static/src/styles/components/下创建局部 SCSS,再通过styles/index.scss聚合,避免回落到全局样式。 - 主题扩展:如需暗色/高对比主题,可在
base/_tokens.scss内维护多套 map,并通过@mixin输出 CSS variables。 - 旧入口兼容:登录/终端等仍引用
/static/style.css,更新后务必同步npm run build以生成最新dist/assets/main.css,否则旧入口将缺少样式。 - 快照对比:大规模改动前可先复制
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品牌体验不变。