Files
ttstd-infinite-canvas/docs/plans/home-chat-optimization-plan.mdx

157 lines
16 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 首页对话区优化计划(BoardUI 参照自研)
> 状态:已确认执行顺序(2026-09-06)——Phase A 先行、随后 Phase B;代码高亮启用 `@streamdown/code`
> 关联:`docs/plans/boardui-absorption-plan.mdx`(图标/工具栏/空态已完成并落版)、`docs/plans/ui-kit-rollout-plan.mdx`
> 范围文件:`web/src/pages/create/index.tsx`(1897 行)、`web/src/styles/globals.css`(15940 行)、`web/src/components/ai/ai-message-markdown.tsx`
## 1. 背景与目标
首页(`/` = 创作页)对话区仍有多处可优化,用户点名两大方向,缺一不可:
1. **历史会话弹窗**:按钮入口 → 弹层内容 → 列表项 → 行内操作,整体打磨。
2. **消息正文富内容**:AI 回复中渲染的文本、**代码块、表格、图片**等内容形态的呈现质量。
工作方式:以 BoardUI 仓库(`../boardui`)为视觉与交互参照**自研**落地;自研过程中如发现本站代码不合理(硬编码、重复、缺无障碍、结构性膨胀),同步改进——但不引入 BoardUI 的运行时依赖(无 `react-aria-components`、无 `motion`,沿用 AntD + Tailwind + 自研 token)。
### 调研结论速览
**BoardUI 侧**(`components/application/agent-chat/*`):
- 对话外壳为「右侧会话 rail + 主消息区 + 底部输入条」三段式卡片(rail 260px 卡片、主区 `rounded-3xl bg-secondary`、输入条同宽贴底)。
- 会话 rail 交互最值得吸收:行 hover 与选中同底色(hover 即预览选中);行尾时间徽标 hover 时淡出让位给「⋯」菜单(190px 浮层:重命名/标未读/删除,删除项红色);**行内重命名**(自聚焦全选、Enter 提交、Esc 还原、blur 提交);未读蓝点 6px;新建会话置顶按钮行;分组小标。
- 消息行操作簇:hover 显露、`focus-within` 保留、流式中禁用隐藏(28px 圆形、`rounded-md`、tertiary 图标色、hover 底色)。
- 用户消息为右侧气泡:`max-w-[75%] rounded-2xl px-3 py-[11px] bg-background-primary shadow-card`;assistant 通栏无气泡,与消息簇同宽(`max-w-3xl`)排版。
- 输入条为 52px 胶囊 + 36px 圆形控制钮;发送中变「停止」;下方一条 26px 状态行如实显示 provider/消息数。
- 空态:标题 + 次级说明 + 胶囊建议钮;首 token 到达前以「思考中」占位。
- **注意**:BoardUI 的 agent-chat 是纯文本 starter,全库无 markdown/代码块/表格/图片渲染组件(已 grep 证实:无 react-markdown/shiki/prism/`language-` 类)。故**富内容方向以本站自研管线为主干**,BoardUI 仅提供容器语汇(chip/复制钮/滚动容器/间距节奏)。
**本站侧现状**(引用为现状快照,实施前以最新行号为准):
- 消息渲染:assistant 消息头含镜头徽标/模式/模型/时间/状态与「生成同款」,推理过程可折叠(`MessageReasoning`),正文经 `AIMessageMarkdown`(`web/src/components/ai/ai-message-markdown.tsx`,streamdown 流式渲染,`parseIncompleteMarkdown`,逐词淡入)。
- 富内容现状(样式见 `globals.css` 15206–15297):
- 代码块:仅有衬底 pre(`rounded r-sm`、`foreground 7%` 底),**无语言标签条、无复制按钮、无行号**(`lineNumbers={false}`)、无语法高亮。依赖 `@streamdown/code@1.1.1` 已安装但**从未被 import**(沉睡资产,即流式高亮的官方配套)。
- 表格:滚动容器 + 单元格仅下边框 + 表头 5% 底,较朴素;无边框网格/斑马纹/圆角容器。
- 图片:markdown 内 `![...]` 无自定义渲染(无圆角/尺寸约束/点击预览);会话内生成结果以媒体卡片网格呈现并有预览 Modal(含缩放拖拽),此路已通。
- 引用/列表/分割线/行内代码:已有 token 化样式(`color-mix(in srgb, currentColor …)` 自适应明暗)。
- 历史弹窗现状(`index.tsx` `CreationHistoryDrawer` 段):AntD Drawer;含标题计数、搜索框、新建会话卡、时间桶分组(今天/昨天/近 7 天/更早)、行=整行按钮 + 直接删除按钮 + 模式 tag + 摘要截断、空态、`aria-current`。已不粗糙,但与 BoardUI rail 相比缺少:**hover 菜单(重命名/删除并入)、行内重命名、未读标记、时间徽标让位动画、行间 hover 反馈一致性**;「删除」为单点直达按钮存在误删风险(删除虽走确认流程)。
- 输入条:已完成 R2 幽灵按钮统一(32px 透明按钮族),与消息区为同一 820 居中列。
## 2. 待优化清单(分阶段)
### Phase A — 历史会话弹窗升级(借鉴 BoardUI rail 交互)
目标:让「历史」弹窗的列表行达到与 BoardUI rail 同级的信息密度与操作安全度,并补齐行内编辑。
- [ ] A1 行操作重构:删除从「常驻小按钮」改为 hover「⋯」菜单(菜单项:重命名 / 删除[红]);hover 态即选中预览底色;键盘可达(按钮 `aria-expanded`、菜单 Esc 关闭、焦点回退触发器)。
- [ ] A2 行内重命名:行标题双击或菜单「重命名」进入编辑态——输入自聚焦全选,Enter 提交 / Esc 还原 / blur 提交;提交走既有改名逻辑并乐观更新。
- [ ] A3 时间徽标:展示相对时间(刚刚/n 分钟/n 小时/n 天前),hover 行时让位给操作菜单(淡出/淡入,`prefers-reduced-motion` 下直接切换)。
- [ ] A4 行信息补全与排版:摘要截断行 + 消息数/时间粒度统一;选中态、hover 态、焦点环与页面其他按钮族同源(沿用 R2 幽灵钮规范)。
- [ ] A5 空态与加载态核对:无历史时按钮/面板空态文案与插图风格对齐首页空态;打开时骨架或已有加载态统一。
- [ ] A6 删除确认保留既有确认流;确认框按钮规格对齐全局。
验收:悬停/键盘可完成重命名与删除;重命名即时生效;删除需确认;明暗两主题下 hover/选中/焦点可辨;`bunx tsc --noEmit` 通过;提交后浏览器人工验收。
### Phase B — 消息正文富内容打磨(文本/代码块/表格/图片)
目标:AI 回复中的结构化内容达到「可读、可复制、可引用、好看」的水准。以 `AIMessageMarkdown` 的 components 映射为单一扩展点,不另起渲染体系。
- [ ] B1 代码块外壳:语言标签条(语言名取自 `className="language-*"`,未知语言不显示或显 `code`)+ 复制按钮(`aria-label`、成功态反馈)+ 统一圆角/边框/底色 token;横向滚动保留;顶部标签条在流式渲染中稳定不跳动。
- [ ] B2 代码高亮:评估启用 `@streamdown/code`(流式友好,已装未用)。决策点见 §4。若启用需处理:未知语言降级、流式增量着色节流、深色主题 token 化(不引入散落色值)。
- [ ] B3 行号(可选):streamdown 已支持 `lineNumbers`(当前显式关闭)。默认关闭(对话场景非编辑器),提供设置/偏好开关的可行性标注即可,不强推。
- [ ] B4 表格增强:网格边框(弱化)+ 表头底色 + hover 行、粘性表头容器?——对话表格通常短小,做「圆角容器 + 细网格 + 表头 5–8% 底」即可,不引入复杂表格库;列多时滚动容器保留并补滚动提示(可选)。
- [ ] B5 行内图片:markdown `![alt](url)` 渲染为受限尺寸圆角卡片(`max-height` 约束、`object-fit: cover/contain` 由比例定)、点击进入既有预览 Modal(复用生成结果预览组件);加载失败占位(alt 文案 + 破损图标);懒加载。流式期间图片未收尾时的处理与正文一致(不闪跳)。
- [ ] B6 消息级操作簇(如可行且不喧宾夺主):assistant 消息 hover 出现「复制全文/朗读(如已有能力)」等,参照 BoardUI 显示规则(hover 显露、focus-within 保留、流式隐藏);与现有消息头操作区不重复。
- [ ] B7 渲染一致性小修:标题层级字号用 em 但整体应随正文 1em 缩放核验;行内代码与代码块在流式未闭合时的处理(streamdown 已处理,人工验收确认);引用块与代码块间距节奏(`0.8em` 段落间距)核对。
验收:向模型提问触发含代码块/表格/列表/引用内容,肉眼核对明暗主题;代码块复制可用且键盘可达;图片点击预览;流式中无布局跳动;`tsc` 通过;浏览器人工验收。
### Phase C — 代码质量改进(自研中发现的不合理点)
伴随 A/B 落地顺手治理,不单独立项大改:
- [ ] C1 消息正文样式(15206–15297)与代码块新样式统一收口到创作页样式节或提升为共享组件类;新组件(代码块/图片/历史行菜单)优先页面级组件,出现第二处使用时再提升(遵循 AGENTS.md 组件归属规则)。
- [ ] C2 清理内联字面样式(如 `index.tsx` 内 `style={{display:"inline-flex",gap:8}}` 之类散落写法)→ 具名 CSS 类;磁贴/图标尺寸继续走 R3 统一族。
- [ ] C3 时间格式化工具核对:消息时间/会话分组时间/相对时间若存在多套近似实现,合并为一处(验证引用后再删,不臆测)。
- [ ] C4 无障碍核对(随 A/B 每项必查):新增按钮均有 `aria-label`/`aria-expanded`、焦点环、Esc/Enter 语义;`prefers-reduced-motion` 下逐词淡入与让位动画降级为直接切换(若 streamdown 动画类无降级则补 CSS)。
- [ ] C5 `index.tsx` 1897 行:本轮**不拆文件**(页面私有组件合法),但 A/B 新增块保持独立组件定义清晰;若后续页面文件再涨且出现跨页复用再议拆分。
## 3. BoardUI 关键规格速查(实施时对照)
| 能力 | BoardUI 配方 | 本站落点建议 |
| --- | --- | --- |
| rail 行圆角/hover | `rounded-2lg`,hover 与选中同 fill | 历史行 `--r-md`~`--r-lg` 家族,hover 即预览选中 |
| 未读点 | 6px `bg-button-primary` | 会话级未读(如可用 data 支持)否则标注「数据不支持」 |
| 行菜单 | 190px、`p-2`、删除 `text-text-error-primary` | 自制浮层或 AntD Dropdown 定制样式 |
| 时间徽标让位 | 相对时间 hover 淡出让位菜单 | CSS transition + reduced-motion 降级 |
| 用户气泡 | `max-w-[75%] px-3 py-[11px] rounded-2xl` | 已右对齐气泡,核对圆角/内边距/阴影一致性 |
| 消息 hover 操作 | 28px `rounded-md`、流式禁用隐藏 | 消息头已有操作区,评估是否需要消息尾簇 |
| 输入条 | 52px 胶囊 + 36px 圆钮 + 26px 状态行 | 现有 820 幽灵钮族已统一,仅核对与消息区衔接 |
| 空态 | 标题/说明/胶囊建议钮、思考占位 | 已对齐(R2/R3),微调即可 |
## 4. 已确认决策
1. **执行顺序**:Phase A(历史弹窗)先行,随后 Phase B(富内容)——用户已确认(2026-09-06)。
2. **代码高亮方案**:启用 `@streamdown/code`(官方流式配套、已装零新增依赖)——用户已确认(2026-09-06)。实施时:未知语言降级为无高亮;增量着色节流;颜色走主题 token。
3. 行号默认关闭、图片预览复用既有 Modal——按正文推荐默认执行,无异议。
## 5. 落地纪律
- 每个 Phase 独立提交(`feat/fix/refactor` 前缀按仓库规范),提交前 `bunx tsc --noEmit`,改动后同步 `docs/content/docs/progress/pending-test.mdx` 验收段落(含本次删除任务通知已记录的条目)。
- 所有改动保持工作树干净;本计划文档随首轮实施一并提交。
- BoardUI 只读参照;若其视觉与本站 token(明暗自适应)冲突,以本站 token 体系为准。
## 6. 对话消息渲染逐项对照自查(BoardUI 参照)
> 本节按「消息渲染」维度(布局/对齐/气泡/富内容/状态/可达性)逐项列出现状与建议,2026-09-06 代码与 CSS 实测核对。
> 状态图例:✅已对齐|🔧微调(小改)|🛠结构性(中等)|❓待产品决策
### 6.1 布局与对齐
| 编号 | 现状(已实测) | BoardUI 参照 | 建议 | 状态 |
| --- | --- | --- | --- | --- |
| L1 | 会话列 `min(820px, 100% - 48px)` 居中 | 列表同宽居中 | 维持 | ✅ |
| L2 | 助手消息 `width: min(760px, 100%)`,行距原 `space-10`(40px) | 消息垂直间距约 20px、分组更密 | **已实施**:用户/助手消息行距统一降为 `space-8`(32px),长会话视密度更紧凑 | ✅已实施 |
| L3 | 正文列 `padding-left: space-8(32px)`(含头部 mark 对齐) | 无 mark、正文贴左 | 保留 mark 头设计(本站特色);正文/媒体/错误三线缩进统一到 32px | ✅ |
| L4 | 错误/空态行沿用旧 34px 缩进(未见 home 覆盖) | — | **已实施**:新增 home 覆盖 `max-width:720px; padding:16px 0 0 space-8`;窄屏随正文归零 | ✅已实施 |
| L5 | 媒体结果 `max-width 680`、图片 `min(320px)` flex 换行、视频 `min(680px)` | 结果区宽于正文、右缘对齐 | 对齐原则一致;核对图片 gap 与圆角是否 token 化 | 🔧 |
### 6.2 用户气泡
| 编号 | 现状(已实测) | BoardUI 参照 | 建议 | 状态 |
| --- | --- | --- | --- | --- |
| U1 | 气泡为 `copy-wrap`:半径 `r-lg/r-lg/4/r-lg`,`accent 10%` 混底 | `rounded-2xl`(四角 16px)实底 `background-primary` | 尾巴角 4px 是聊天拟物风,保留可;若想更板正可改 16/16/6/16 | ❓ |
| U2 | 气泡原无阴影(`box-shadow:none`) | `shadow-card` | **已实施**:深浅双主题 1px 柔和投影(暗 rgb(0 0 0/.18)、亮 rgb(15 23 42/.08)) | ✅已实施 |
| U3 | 宽度 `min(560px,86%)` 右对齐,内边距原 `10/14` | `max-w-[75%] px-3 py-[11px]` | **已实施**:横向 14→12px,与 boardui `px-3`≈12px 一致 | ✅已实施 |
| U4 | 元信息(你/时间/复制钮)在气泡**上方** meta 行 | 元信息在消息动作行,时间紧随 | 现布局合理;复制钮为幽灵钮 opacity .66→1 | ✅ |
| U5 | 多段/换行由 markdown 渲染 p;无逐段折叠 | 单正文段落 | 维持 | ✅ |
### 6.3 助手消息形态
| 编号 | 现状 | BoardUI 参照 | 建议 | 状态 |
| --- | --- | --- | --- | --- |
| A1 | 头部:mark 块 + 名称 + 模型 + 时间 + 状态徽标 + 变体操作(右缘) | 无头部行、消息下挂操作 | 头部信息密度高(模型/时间常驻);可评估:空闲时模型/时间降为 hover 显示,仅保留名称+状态 | ❓ |
| A2 | 操作在头部右缘(variant-action 幽灵钮) | 28px `rounded-md` 操作钮,`opacity-0`→`group-hover` 浮现,focus-within 常显 | **已实施**:`@media(hover:hover)` 内 hover/focus-within 浮现;触屏(pointer:coarse)保持常显 | ✅已实施 |
| A3 | 思考/流式中间态:pending 帧 + 思维卡片(自研 reasoning) | 独立 thinking 占位(dots/星星/彗星动效、`font-mono` 计时) | **已实施**:流式中 250ms 节流实时秒数(`font-mono tabular-nums`),结束后展示总时长 | ✅已实施 |
| A4 | 生成卡(GenerationToolCard):头部行 + 可折叠正文 | 工具卡以正文内折叠块呈现 | 核对折叠态图标方向与 aria-expanded | ✅ |
### 6.4 富内容与媒体
| 编号 | 现状 | BoardUI 参照 | 建议 | 状态 |
| --- | --- | --- | --- | --- |
| C1 | 代码块:shiki 双主题 + 流式光标(上轮已落地) | — | 复核行号默认关闭、未知语言降级策略 | ✅ |
| C2 | 待生成媒体帧:呼吸渐变 + 取消钮 | — | 与 loader 语义一致,已达标 | ✅ |
| C3 | 视频容器 `aspect-ratio:16/9` 常驻(base 层),home 仅改宽 680;`object-fit:contain` 等比留边 | — | **已核实**:容器比例稳定无闪跳风险,无需改动 | ✅已核实 |
### 6.5 可达性与状态
| 编号 | 现状 | BoardUI 参照 | 建议 | 状态 |
| --- | --- | --- | --- | --- |
| X1 | hover 浮现类动效须尊重 `prefers-reduced-motion` | 同 | A2 隐藏规则仅作用于 `hover:fine` 设备;时长走 `--motion-state`,reduced-motion 由全局规则降级——待浏览器实测 | 🔧待实测 |
| X2 | 行/钮焦点:`:focus-visible` 描边 | `focus-visible:ring-2` | 已一致 | ✅ |
| X3 | 会话列表已接 `role="log"` 与 aria-live | — | 保持 | ✅ |
### 6.6 建议执行顺序
1. ✅ **P1(微调批,已实施)**:L2 行距 32px、L4 错误行 32px、U2 深浅双主题投影、U3 内边距 12px、A2 hover/focus 浮现(触屏常显)。
2. ✅ **P2(结构性,已实施)**:A3 流式 mono 计时(250ms 节流);C3 已核实 base `16/9` 常驻无需改动。
3. ⏳ **P3(待决策,未动)**:U1 圆角风格、A1 头部信息 hover 显隐——等产品定调后实施。
4. ✅ Phase A 历史抽屉(行 hover 菜单/重命名/相对时间)代码已在册;浏览器实测待预览环境补做。