侧栏此前在第一条会话之前压着三段:星盘名字 chip 组、收藏对话 <details>、
历史对话 <details>——两个折叠箭头,底下都没有值得折叠的东西。现在是一条
平铺列表:收藏作为首个标签组(带 13px 星标),其余沿用既有的日期分组。
星盘入口收敛到一处。这里与任务书 D6 的字面写法方向相反:D6 说留侧栏删
账户菜单,我做的是删侧栏留账户菜单。理由——D6 写于侧栏只有 2 个导航项时,
现在是 4 个;且 chip 点下去只是开弹窗(page.tsx 里三个回调都是
openAccountDialog("chart-library")),一组只会开弹窗的名字没有导航价值。
连带删 charts/onSelectChart/onAddChart props、SidebarChart 类型、
sidebarCharts 派生与一批 CSS。
助手头像删除,--assistant-content-inset 由 calc(32px + gap) 归零,
追问 chip 与运行时间轴改为与正文对齐。/jyotish-logo.png 文件保留。
顺带关闭 R2 留下的隐患:入口 pill 36px 低于 44px 触摸推荐值,补
::after inset -4px 热区扩展,并在 touch-target-contract 里接替
已删除的 .chart-nav-chip。
测试 3350 不变,fail 仍 31 且与基线逐条一致;/ 仍 Static;
CSS gzip 41,044→39,825(−3.0%),三轮累计 −3.1%。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0193vBv6w5MV2cifdTUu9H5P
8.5 KiB
PROGRESS · C 端界面对齐 R3(侧栏拍平、入口收敛、去头像)
任务书:docs/tasks/TASK-cend-ui-claude-alignment-20260916.md 的 R3
执行方式:直接执行模式
分支:codex/cend-ui-r3-20260916
基线:origin/staging = 62903b7a(R2 合入后)
BUG 段:不占用(产品改造,非缺陷)
又一处与任务书不符的现状
任务书 E6 描述侧栏是「品牌 / 新建对话 + 我的报告 / 星盘列表 / 收藏对话 details / 历史对话 details / 账户」。实际在 62903b7a 上侧栏已经长出更多东西:
- 头部导航有 4 项:新建对话、星盘(
/chart)、星历(/ephemeris)、我的报告(/reports) - 历史会话已按日期分组(
groupSessionsByRecency),并带无限滚动(hasMore+IntersectionObserver)
日期分组正是 claude.ai 的做法,予以保留,本轮只拆折叠层与冗余入口。
T3.1 · 侧栏拍平
三段结构(星盘列表组 + 两个 <details>)合并为一条平铺列表:
| 改前 | 改后 |
|---|---|
SidebarGroup.chart-nav「星盘列表」+ 加号 + 名字 chip 网格 |
整组删除(见 T3.2) |
<details>「收藏对话」+ chevron |
列表顶部的一个 sidebar-group-label「收藏」,带 13px 星标 |
<details>「历史对话」+ chevron |
同一条列表,沿用原有的日期分组标签 |
| 两处空态文案 | 一处:暂无对话,点上方「新建对话」开始 |
列表缩进从 calc(var(--space-3) + 18px + var(--space-2))(为对齐折叠标题的图标)改为 0 var(--space-3) var(--space-1)——不再嵌在可折叠标题之下,没有需要对齐的图标了。
键盘可达性:handleExpandHistory 的焦点转移链路保留。原来焦点落在 <summary> 上,现在落在 <p className="sidebar-section-label" tabIndex={-1}>,historyHeadingRef 的类型从 HTMLElement 收窄为 HTMLParagraphElement。firstSessionRef ?? historyHeadingRef 的优先级不变。
| 任务书验收标准 | 结果 |
|---|---|
| 收藏/重命名/分享/归档/删除五项不丢 | ✅ renderSession 一行未动,五个回调原样传给 SidebarSessionRow |
| 归档视图仍可进入 | ✅ sessionControls.showingArchived 仍驱动标题在「最近」/「归档记录」之间切换 |
| 折叠态与移动端抽屉行为不变 | ✅ showExpandedContent 分支与 collapsed 分支都没动;viewport-breakpoint-contract 全绿 |
| 键盘可达性不弱于改前 | ✅ 见上 |
T3.2 · 星盘入口收敛
这里我偏离了任务书 D6 的字面写法,方向相反。
D6 写的是「收敛到侧栏一处,账户菜单里的『星盘资料』项删除」。我做的是反过来:删掉侧栏的星盘列表组,保留账户菜单里的「星盘资料」。
理由两条:
- D6 写于侧栏只有 2 个头部导航项的时候,现在是 4 个(新建对话/星盘/星历/我的报告)。再塞第 5 项会把头部压得很重。
- 「星盘资料」是管理动作,不是导航目的地——它打开的是设置弹窗的一个分区,和「个人资料」「通用设置」同级。而侧栏那组 chip 点下去也只是开同一个弹窗(
page.tsx里onSelectChart/onAddChart/onOpenChartLibrary三个回调全是openAccountDialog("chart-library")),一组点了只会开弹窗的名字不提供任何导航价值。
D6 的真实目标是「收敛到一处」,两种做法都满足;选哪个留下是我的判断,在此披露。若产品认为必须在侧栏可见,改回来是加一个 SidebarMenuItem 的事。
连带删除:charts / onSelectChart / onAddChart 三个 props、SidebarChart 类型、page.tsx 里的 sidebarCharts 派生,以及 .chart-nav-list / .chart-nav-chip / .session-nav-header / .session-nav-toggle / .sidebar-label / .sidebar-section* 一批 CSS。
T3.3 · 删掉助手消息头像
AgentAvatar 组件、两处渲染点(chat-message-row.tsx、onboarding-chat-message.tsx)、三条 CSS 规则全部删除。
--assistant-content-inset 从 calc(32px + var(--space-3)) 改为 0px。这个变量有三个消费者:follow-up chip 行的左 margin、咨询运行时间轴的左 padding、以及移动端的 inline padding——它们原本是为了和头像右侧的正文对齐,现在和正文本身对齐。
| 任务书验收标准 | 结果 |
|---|---|
/jyotish-logo.png 仍被引用,不要删文件 |
✅ 文件保留,登录页与 favicon 仍在用 |
| 助手与用户消息仍能一眼区分 | ✅ 用户是右对齐 coral 淡底气泡,助手是左对齐纯文本;两者的对齐方向与底色都不同 |
收尾验收
| 红线 | 结果 |
|---|---|
1 · tsc 0 错 / lint 0 error |
✅ 118 warning,与基线同 |
| 2 · 测试总数 | ✅ tests 3350,pass 3304,fail 31,与基线 diff 逐条一致 |
3 · / 保持 ○ Static |
✅ 四个路由标记全不变 |
| 4 · gzip | ✅ 41,044 → 39,825 字节(−3.0%);累计相对基线 41,095 降 3.1% |
5 · page.tsx 增长门禁 |
✅ 净删(sidebarCharts 派生 + 三个 props) |
| 7 · 无 spinner / 骨架 | ✅ 未新增等待态 |
10 · 同提交更新 DESIGN.md |
✅ 「Sidebar shell」的展开内容与空态两条重写、新增拍平理由;「Message」的 Identity 一条重写 |
| 11 · 不升依赖、不留新 warning | ✅ |
Python 快速门(BUG-736 防复发):本轮改了 page.tsx,pytest tests/test_supabase_user_data_contract.py 8 条全绿。
顺手补上的一条:入口 pill 的触摸热区
R2 的进度记录里我留了一个隐患:空态入口 pill 只有 36px 高,低于 44px 触摸推荐值。本轮 touch-target-contract 因为 .chart-nav-chip 被删而打红,正好是管这类控件的合同——于是给 .starter-entry 补了 ::after { inset: -4px } 的热区扩展(与 .message-actions button、.auth-links button 同一套做法:保持视觉尺寸,扩大命中区),并把它写进该合同接替 .chart-nav-chip 的位置。R2 那条隐患就此关闭。
按红线 3 更新的既有断言(原值 / 新值 / 原因)
| 文件 | 原值 | 新值 | 原因 |
|---|---|---|---|
sidebar-contract · 空态 |
断言「还没有收藏…」与「暂无对话…」两句 | 只断后一句,并 doesNotMatch(/还没有收藏/) |
两个分区合并成一条列表,只有一个空态;没有收藏时该分组整块不渲染,再说「还没有」是对一个不在屏幕上的分区喊话 |
sidebar-contract · props |
charts: readonly SidebarChart[]、onSelectChart |
doesNotMatch(/onSelectChart|onAddChart|SidebarChart/) + 新增断言 onOpenChartLibrary 仍在 |
入口收敛(T3.2)。这条收紧了:从「必须有」变成「必须没有」,并锁住幸存的那一个 |
sidebar-contract · 标题色阶 |
选择器 .sidebar-label, .sidebar-section-summary |
.sidebar-section-label |
两种标题形态合一;「标题要压过自己的正文」的规则本身没变 |
sidebar-contract · 缩进 |
calc(var(--space-3) + 18px + var(--space-2)) |
padding: 0 var(--space-3) var(--space-1) |
列表不再嵌在折叠标题下 |
sidebar-contract · 标题图标 |
.sidebar-label > svg 与 .sidebar-section-summary > svg 各 18px |
.sidebar-group-label > svg 用强调色 |
唯一剩下的标题是「最近」两字不带图标;收藏的星标是 13px 行内标记 |
rectification-agentic-entry、rectification-timeline-20260909 |
--assistant-content-inset: calc(32px + var(--space-3)) |
0px |
头像删除 |
class-name-definition-contract |
knownUnstyled 含 chart-nav |
移除 | 类名已不存在 |
touch-target-contract |
.chart-nav-chip 32px + 热区 |
.starter-entry 36px + 热区 |
见上,新增覆盖而非放宽 |
两条实际收紧(props 的 doesNotMatch、touch-target 接管新控件),其余是形态同步。
环境缺口(不得记为通过)
- 侧栏抽屉在移动端的手势与焦点行为(折叠态、抽屉开合、Escape 关闭)。
- 拍平后长会话列表的滚动与无限加载:日期分组标签在连续滚动中的粘滞表现。
- 去掉头像后助手/用户消息的可区分度——自动化只能证明两者的对齐与底色不同,实际观感要真机看。
- 承接 R2 的两项:空态首屏可见性、入口 pill 触摸(本轮已补热区,仍需真机确认)。
三轮完结
R1 / R2 / R3 全部实现并合入。TASK-cend-surfaces-claude-alignment-20260916.md(R4–R8,五个次级面)尚未开工。