Files
agent-frontend-web/docs/superpowers/specs/2026-08-07-frontend-context-popover-theme-fix-design.md
T
2026-08-08 17:28:57 +08:00

3.2 KiB
Raw Blame History

Frontend 上下文窗口 popover 主题适配 — Design Spec

日期: 2026-08-07 状态: Approved 范围: Bug 修复(CSS 变量 / Element Plus Teleport

背景

src/views/frontend/components/InputArea.vue 中的"上下文窗口"指示器(.context-indicator)点击后弹出 el-popover,其中显示 token 使用量、阈值百分比等。当前问题是:该 popover 没有适配 frontend 的深 / 浅色主题。

根因

Element Plus 的 el-popover 默认 teleported: true(已确认,源码 element-plus/es/components/tooltip/src/content.mjs),弹出层被 Teleport 到 body 之外。

body[data-fe-theme="light"] 只覆盖了 --fe-* 系列变量,未覆盖 Element Plus 内部用到的 --el-bg-color-overlay--el-border-color-lighter--el-text-color-regular 等。结果是:

  • popover 容器(.el-popper)回退到 Element Plus 默认值(浅色背景 + 浅色文本)
  • 在深色主题下,与 frontend 整体深色风格不一致
  • .context-popover 内部的 --fe-* 变量虽然继承自 :root,但 popover 容器本身的背景 / 边框 / 文字色来自 --el-*,这些没被覆盖

方案

el-popover 设置 :teleported="false",让 popover 容器保留在 .frontend-container DOM 树内,从而继承 .frontend-container 下的所有 --el-* / --fe-* 变量映射。

改动点

src/views/frontend/components/InputArea.vue 第 81-85 行的 el-popover 标签,新增 :teleported="false"

<el-popover
  placement="top"
  :width="280"
  trigger="click"
  :teleported="false"
>

.context-popover 现有的 scoped 样式(.popover-title / .popover-body / .popover-footer / .token-count)保持不变,因为它们使用 --fe-* 变量,本来就能工作。

不需要改动

  • theme.scss.frontend-container 已经把 --el-bg-color-overlay--el-text-color-regular--el-color-success--el-color-danger 等都映射到 --fe-* 变量,只要 popover 在 .frontend-container 内就能自动生效
  • 浅色覆盖:.frontend-container[data-theme="light"] 同样完整覆盖了 --el-* 系列
  • .context-popover 的 scoped 样式:因为 .context-popover 本身在 InputArea 模板中,scoped 的 data-v-xxx 仍会附加到元素上,popover 留在组件树内后所有选择器自然匹配

验证

  1. 切到深色主题,点击输入框右下角的"XX%"指示器 → popover 应为深色背景(#252526 / --fe-bg-elevated)、浅色文字
  2. 切到浅色主题,点击同一指示器 → popover 应为白色(#ffffff / --el-bg-color)、深色文字
  3. 百分比 el-tag:深色主题下 success 是青色(#4ec9b0),danger 是珊瑚红(#f48771);浅色主题下 success 是蓝色(#1890ff),danger 是红色(#f56c6c
  4. token-count 文字:深色下青色,浅色下蓝色
  5. 重复点击 / 多次切换主题,popover 位置不漂移、不被聊天内容遮挡

非目标

  • 不改 el-popover 的其它属性(placement、width、trigger
  • 不改 theme.scss
  • 不改 .context-popover 现有样式(变量已经够用)
  • 不动 el-tooltip(左下角 @ 按钮的 tooltip,独立组件,独立处理)