Poco 使用手册
开发指南

主题视觉验收与踩坑手册

Poco 多主题页面的审美基线、问题诊断经验、验收矩阵和回归记录模板。

本文是主题系统与前端配色开发手册的实践配套,记录 New Steel 从设计、接入到全页面调优过程中真正暴露的问题。

它不要求所有主题长得一样,而是确保每套主题都满足同一组视觉关系:

  • 页面画布、内容 Surface、嵌套区域和浮层层级清楚。
  • Default、Hover、Selected、Active、Focus 不会互相混淆。
  • 品牌色有识别度但不过量。
  • 功能色和文字前景符合语义。
  • 切换主题只改变视觉,不改变布局和行为。

审美基线

1. Surface 要稳定,强调色要克制

Light 中,独立卡片、公共页头、表格、历史消息区、Dialog 和工具执行区域通常需要稳定 Surface。不要让它们透出页面画布,也不要把全部区域机械染成主题色。

主题色优先用于:

  • 主按钮、链接和可点击图标。
  • 当前导航、Selected 和 Focus。
  • 小面积身份、状态或强调标记。

主题色不应直接铺满:

  • 大面积业务卡片 Hover。
  • 整个表头或公共页头。
  • 密集 Badge 列表。
  • 普通正文和说明文字。

2. Hover 是反馈,不是换一个页面层级

Hover 应让用户知道“这里可交互”,但不能:

  • 变得和 Selected 几乎一样。
  • 变得接近页面画布,像卡片突然消失。
  • 使用过重阴影,像 Popover。
  • 改变尺寸、内边距、排列或文本换行。

中小面积导航、选项和表格行可以使用主题 Hover 背景;大卡片更适合保持 Surface,通过边框、轻阴影和小幅抬升反馈。

3. 默认状态保持安静

静态卡片默认使用中性边框。主题色边框只用于 Hover、Selected、Focus 或明确业务状态。

如果所有卡片默认都有彩色边框,页面会持续处于“已选择”或“需要注意”的视觉噪声中。MCP 卡片最终与 Skills 卡片统一:默认中性边框,Hover 才出现弱主题色边框。

4. 文字层级必须可读

  • 主文字负责内容。
  • Secondary 负责可连续阅读的说明。
  • Muted 负责时间、ID 和元信息。
  • Disabled 只负责真正不可用的控件。

不要把所有非标题文字都降成 Muted。视觉“轻”不等于可读性低。

5. 实底必须配套前景

蓝色、红色、绿色等实底上的文字和图标必须使用对应 Solid Foreground。尤其是危险按钮,Light/Dark 都需要单独确认;不能因为 Dark 的某个前景可用,就让 Light 出现红底黑字。

6. 默认主题是产品资产

新增主题不是重做全站。Classic 的原有观感必须通过安全默认 Token 保留。任何新语义角色都先定义 Classic 等价值,再提供新主题映射。

7. 配色不承担布局职责

主题语义类只负责颜色、边框和必要阴影。公共头“缺背景”时只补背景,不能同时增加 Padding、圆角、Overflow 或改变 CardContent 结构。

诊断问题时先记录四件事

每次开始排查前先记录:

  1. 主题方案,例如 classicnew_steel
  2. 模式,例如 Light 或 Dark。
  3. 路由和数据状态。
  4. 交互状态,例如 Default、Hover、Selected、Disabled。

同一个组件在不同组合下可能走不同变量。没有这四项,“这里颜色不对”很容易被修成另一个范围的回归。

真实踩坑与正确处理

色板和前景

现象根因正确处理回归检查
蓝色主按钮明显过深--primary 误用了 Active 色分离 Default、Hover、Active Token检查 Button 三态和链接
状态色整体发暗、发脏为局部对比度把功能色混入深色先遵守确认色板;确需调整则新增全局状态前景检查 Badge、图标和图表是否被误改
红色按钮出现黑字Light 继承了不合适的实底前景使用 --destructive-foreground,逐模式核对删除、停用和失败操作
标签像一排主按钮Badge 使用品牌色实底默认使用 Subtle 背景和功能色前景密集状态列表和表格
页面所有灰字一个层级Secondary、Muted、Disabled 混用按可读说明、元信息、禁用拆分长说明、时间、Placeholder

Surface 和透明背景

现象根因正确处理回归检查
设置弹窗、公共页头像没有背景独立区域沿用透明或 Page Background使用 Card/Popover 或对应 theme-surface-*Dialog、固定头、滚动内容
历史消息区和工具卡片透底工具步骤、输入输出只用了通用弱透明色使用 theme-tool-steptheme-tool-payload折叠、展开、长 JSON
文本产物预览混入页面画布Markdown 阅读区直接使用 Page Background使用 theme-artifact-text-preview 明确阅读表面普通预览、沉浸预览和编辑预览
表格头、卡片头露出页面底色头部没有自己的 Surface使用表头语义类,仅补颜色Padding、圆角、边框不能变化
卡片圆角边框在四角出现断线不透明子 Surface 覆盖父级圆角边框共享 Card 首尾区域继承外层圆角,不全局裁剪内容Header、Content、Footer
表单弹窗内部卡片层级不自然Body、一级表单卡片和 Page 混用背景使用 theme-form-dialog-bodytheme-form-section新增和编辑弹窗
分享页没有主题识别度全页只使用通用背景和文字用分享页语义表达少量身份和状态强调Classic/Dark 保持各自风格
选中卡片反而接近页面底色bg-primary/5 与 Page 混合使用稳定的 theme-card-selectedLight/Dark 都检查

Hover、边框和阴影

现象根因正确处理回归检查
大卡片 Hover 变成大片蓝色把导航级 --surface-hover 用在大卡片保持 Surface,以边框和轻阴影表达工作台、发布页、能力卡片
Hover 后卡片像融入页面画布Hover 背景接近 Page Background使用 Card Surface 或稳定 Hover Token查看边界是否仍清楚
Hover 阴影像浮层卡片复用了 Popover 级 shadow-md使用卡片级阴影语义与 Dialog、Popover 对比
所有 MCP 卡片默认彩色边框Enabled 被直接当作 Selected默认中性边框,Hover 才用弱主题色Disabled 和 Selected 不混淆
能力卡片 Hover 突然整块变蓝通用 theme-hover 用于较大能力卡片使用 theme-capability-card-hoverClassic 和 New Steel Dark 不回归

Tabs、导航和图标

现象根因正确处理回归检查
Inactive 与 Active Tab 太像List、Inactive、Hover、Active 共用近似背景分别定义 --tab-* 状态放在白色和非白色父背景上
Inactive Tab 直接设白后消失只针对当前父背景调色Inactive 与 List 分开建模Surface、Subtle 两种容器
Tab 文字变色但图标不变图标有独立固定颜色图标使用 currentColor 或继承 TriggerLucide 图标与自带语义图标
Badge 没跟随 Active状态选择器写在没有 data-state 的子元素上使用 group-data-[state=active]数量 Badge、装饰图标
下划线 Tabs 变成块状标签页面自己复制普通 Tabs 状态类使用共享 variant="line"定时任务详情等导航
点击侧栏文字闪一下主题色:active 复用了彩色选中前景使用独立 Pressed 前景 TokenLight/Dark、选中和未选中项

输入、共享组件和第三方控件

现象根因正确处理回归检查
Dark Composer 内出现一块异色输入背景内层 Textarea 的 Dark 背景覆盖父级 Surface仅在组合输入中使用 bg-transparent dark:bg-transparent普通表单 Input 不能一起变透明
Light 输入框全选后像没有选中选择状态误用了过浅的 Accent/Hover 背景使用独立 --text-selection-* 语义,并分别映射前景和背景Input、Textarea、组合输入框
React Flow 等第三方控件出现亮色泄漏第三方默认 CSS 不消费项目 Token在组件作用域映射 Card、Border、AccentLight/Dark 控件按钮和面板
修复一个页面导致所有 Dialog 改变全局共享组件被过度覆盖判断问题是共享默认还是特定业务角色全站常见 Dialog 冒烟
主题类生效但下一主题容易忘记组件依赖主题专用选择器建立项目语义 Token,并加入机器契约componentStateTokens 完整

默认主题和维护方式

现象根因正确处理回归检查
New Steel 正常,Classic 工具卡片变深新语义没有提供 Classic 等价默认值先还原 Classic 基线,再单独映射新主题对照 main 或变更前截图
颜色修复顺手改变布局用主题适配重写组件结构把颜色语义和布局类分开修改对比 DOM、间距和响应式
问题越修越多,形成补丁地狱每个页面复制颜色覆盖上移到 Token 或共享组件搜索同类 className
只检查首页就宣布完成动态页、公开页、浮层使用不同组合按页面类型和状态矩阵验收保存覆盖记录

修复层级选择

观察结果应修改的位置
同一主题内所有主按钮都错主题基础 Token 或共享 Button
所有主题的同一共享组件都错共享组件
只有某主题的同一视觉角色错该主题的项目语义映射
多个页面出现同类新角色新增项目语义 Token 和 theme-*
仅一个业务状态确实特殊业务组件的最小语义例外

禁止用以下方式绕过判断:

className={themePreset === "new_steel" ? "bg-white" : "bg-muted"}

也不要把主题 ID 包装成 Tailwind 自定义变体后散落到页面。它解决了眼前选择器,却把下一主题的遗漏变成必然。

页面验收矩阵

不要维护固定路由清单。先从当前源码盘点,再按页面类型抽取有代表性的真实数据:

rg --files frontend/app | rg '/page\.tsx$'

必查页面类型

  • 登录页、首页、全局导航和用户设置。
  • Agent 工作台、任务创建、临时对话。
  • 历史消息、运行中会话、工具执行、产物和实时电脑区域。
  • Skills、MCP、Plugins、定时任务、发布中心等能力页面。
  • 管理后台的概览、表格、筛选、表单和详情。
  • Agent、Conversation、Publish 等公开分享页。
  • 具有真实 ID 的动态详情路由。
  • 文档站本身。

必查表面

  • Page、Card、Popover、Dialog、Sheet、Drawer。
  • 公共页头、卡片头、表格头和表格正文。
  • 历史消息区、工具步骤、输入输出载荷。
  • 表单 Dialog Body、分组卡片、Input 和 Textarea。
  • 空状态、加载骨架、错误提示和 Toast。

必查交互状态

  • Primary:Default、Hover、Active、Focus、Disabled、Loading。
  • Destructive:Default、Hover、Focus、Disabled。
  • Card:Default、Hover、Selected、Disabled。
  • Tabs:List、Inactive、Hover、Active、图标和 Badge。
  • Table:Header、Row Hover、Selected、Empty、Loading。
  • Success、Warning、Danger、Info:浅色和必要的实底状态。
  • Sidebar:Default、Hover、Selected、Pressed、Focus。

必查模式和视口

新主题完整验收至少覆盖:

维度基线
主题Classic、新增主题
模式Light、Dark
桌面1440 × 900
中间宽度1024 × 768
窄屏390 × 844

局部维护任务按用户指定范围执行,但必须确认未修改主题和模式没有被全局 Token 或共享组件意外影响。

稳定触发交互状态

状态推荐方式
Hover指针停留,观察背景、边框、前景和阴影
Active / Pressed保持按下,确认不闪色、不位移
Focus使用 Tab 键,不用鼠标点击代替
Disabled保持必填项为空或使用不可用分页按钮
Loading在非生产环境减慢请求,确认宽高稳定
Empty使用无结果搜索词或专用测试数据
Error仅在非生产环境阻断目标请求或使用失败记录
Destructive Dialog打开后检查,验收时点击取消

无法稳定触发的状态标记“未覆盖”和原因,不能根据默认外观推断通过。

验收记录模板

路由/组件主题模式视口状态结果备注/截图
/zh/examplenew_steelLight1440 × 900Default、Hover通过/未通过问题说明

每个问题至少记录:

现象:
主题 / 模式 / 路由 / 状态:
实际计算色:
期望语义角色:
修复层级:
回归范围:

通过标准

  • 页面画布与独立 Surface 层级清楚,没有无意透底。
  • Primary Default 没有误用 Hover 或 Active 色。
  • 实底按钮、状态和图标使用正确前景。
  • Hover、Selected、Active、Pressed 可以区分且不改变布局。
  • 大卡片 Hover 不会铺满过强主题色,也不会融入页面画布。
  • Tabs 在不同父背景上仍能区分 Inactive 和 Active,图标同步状态。
  • 表头、卡片头、Dialog、工具卡片和历史消息区都有稳定表面。
  • 文字层级清晰,重要说明没有被误降为 Muted。
  • Classic 和未修改模式保持原有观感。
  • 没有硬编码颜色、主题 ID 判断或局部主题补丁泄漏到业务组件。
  • 状态同时包含文字、图标或可访问名称。
  • 桌面和窄屏没有新增溢出、错位或操作不可见。

何时停止继续调色

满足以下条件时应停止局部微调,回到设计或语义层重新确认:

  • 同一状态在三个以上页面需要不同临时色。
  • 只有继续加入透明度或 color-mix(...) 才能勉强可见。
  • Hover、Selected 和 Page Surface 已无法稳定区分。
  • 为了配色开始修改布局。
  • 修复当前主题必然破坏 Classic。
  • 无法说明当前颜色代表的语义角色。

主题适配的目标不是让每个角落都带品牌色,而是让用户在长时间使用时感到稳定、清晰和舒适。

On this page