375px 下读数第四项被 ellipsis 裁成「已…」、第五项整项不可见:compact
段仍加 44px 头像缩进(每侧 60px,可用内容只剩 255px),而 cfb41daf 又把
读数从四项变成五项,按 13px 逐字估宽需要 383px。compact 段改为只取
`space-4`、`column-gap` 收到 `space-2`、第五项 `已对照 N 件` 在 767px 以下
`display: none`(仍在 DOM 与轴 aria-label 里),四项约 292px / 可用 343px。
桌面段、条高 64/56px、滚动锚定逻辑均未动。
「跳到最新」浮层占 composer 上方 56px 带,而 `.message-list` 底部留白恰好
也是 56px,末条选项贴在浮层按钮正下方、正中间点不动。留白改为
`calc(clearance + space-3)`,静止时末条下方 84px = 56px 带 + 28px 空气;
`.conversation` 追加同高 `scroll-padding-block-end`。浮层位置、居中与可见
条件未动。
顺带记一条待产品裁决的口径冲突:DESIGN §10 禁列表写明「已对照 N 件经历」
不上条、仍归交付卡,`cfb41daf` 却把它加上且未改 DESIGN;本轮只在手机上把
它移出可见行,桌面保留原状。
BUG-918、BUG-919
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JUei7K13cYxLHE3Axe4A45
9.5 KiB
进度记录 · 校正页移动端:时间轴读数被裁、「跳到最新」压住选项(2026-09-17)
任务书:docs/tasks/TASK-rectification-mobile-timeline-readout-20260917.md
分支:codex/rectification-mobile-timeline-readout-20260917,基线 origin/staging = c32f81e7(任务书写的 8d7dfbf0 已被 staging 超车,按指令取 c32f81e7)。
BUG:918、919。纯前端样式,未跑 Python 预检(AGENTS §9 允许)。
未触碰(并行会话所有):frontend/src/components/rectification-agentic-chat.tsx、frontend/src/lib/rectification-agentic/**、Python、Skill。也未动时间轴固定高度(64 / 56px)与 use-conversation-scroll-anchor。
1. 做了什么
| 任务 | 文件 | 改动 |
|---|---|---|
| T1 BUG-918 | frontend/src/app/globals.css |
@media (max-width: 767px) 段:.rectification-timeline 的 padding-inline 由 calc(var(--space-4) + var(--assistant-content-inset)) 改为 var(--space-4);.rectification-timeline__readout { column-gap: var(--space-2) };.rectification-timeline__dated { display: none }。桌面段未动。同时改掉基线注释里「四项短文本在 375px 下还有余量」这句被实证推翻的话。 |
| T1 BUG-918 | frontend/src/components/rectification-timeline.tsx |
只加注释:五个 span 永远无条件渲染,由 CSS 决定窄屏显示几项;轴 aria-label 仍由五项拼成;再加第六项必须重算宽度预算。无行为改动。 |
| T2 BUG-919 | frontend/src/app/globals.css |
.rectification-workspace__chat .message-list 底部留白由 var(--rectification-jump-clearance) 改为 calc(var(--rectification-jump-clearance) + var(--space-3));.conversation 追加 scroll-padding-block-end: var(--rectification-jump-clearance)。--rectification-jump-clearance 取值未变(时间轴 56px 条高仍与它同源,既有断言不受影响);浮层的位置、居中、可见条件未动。 |
| T3 | docs/BUG_HISTORY.md、CHANGELOG.md、frontend/DESIGN.md、docs/testing/…、本文件 |
记录。 |
2. 宽度预算(T1 的算术)
jsdom / happy-dom 不在本套件里,scrollWidth 与 clientWidth 都量不到,所以这是按逐字保守估宽的算术,不是测量。每字宽度一律向上取整(数字取 0.6em,而 -apple-system / Helvetica 的 tabular 数字约 0.556em),font-size 13px。测试里 readoutWidthPx 就是这套系数。
单项估宽(px):04:48–05:07 77.5、20 分钟 45.2、代表分钟 04:53 91.1、已答 6 题 54.1、已对照 3 件 67.1。
| 改前 | 改后 | |
|---|---|---|
| compact 每侧内边距 | 16 + 44 = 60px | 16px |
| 375px 可用内容宽 | 255px | 343px |
| 可见项数 / 列间距 | 5 项 / 12px | 4 项 / 8px |
| 读数需要宽度 | 383.0px | 291.9px |
| 375px 余量 | −128.0px(被裁) | +51.1px |
| 390px 余量 | −113.0px | +66.1px |
| 320px 余量 | −143.0px | −3.9px |
375 与 390 两个目标宽度都放得下。320px 差约 4px:按系统实际字宽(数字 0.556em)重算是 283.3px ≤ 288px,能放下;按上面的保守系数差一点点。真机 320px 若尾部被裁一点属已知边界,已写进 docs/testing/ 清单第「已知边界」段,范围和代表分钟在任何情况下都不会被裁。
让步顺序:没有用到。任务书让步 1(只做去 inset + 缩 gap)算下来是 5 项 335.0 + 4×8 = 367.0px > 343px,仍然放不下,所以第五项必须离开可见行;采用了任务书 T1 里的「只保留一项」分支,而不是合并成「N 题 · N 件」——合并需要原始计数,而计数只以 已答 6 题 / 已对照 3 件 这种成品字符串到达组件,要么去改 frontend/src/lib/rectification-timeline-scale.ts(超出本单文件范围),要么在组件里正则抠数字(脆弱)。隐藏这一项另有 DESIGN 依据,见第 4 节。
3. 「跳到最新」的几何(T2)
浮层占 composer 上方 56px 的带:按钮 44px + 浮层自身 padding-bottom: var(--space-3)。基线 .message-list 底部留白恰好也是 56px,与带严丝合缝,末条内容顶到按钮正下方;容器 pointer-events: none 只放行 44px 按钮本体,而按钮居中,正落在选项行中央 → 「遮一半 + 中间点不动」。
改后:.message-list 68px + .conversation 16px = 静止时末条下方 84px = 56px 带 + 28px 空气。
做不到、也没有假装做到的部分:把「任何滚动位置都不重叠」做成保证,需要留白 ≥ conversationAnchorThreshold(96px) + 56px = 152px。推导:设末条内容底为 E、尾部留白 P、距底 d,浮层带覆盖内容坐标 [E+P-d-56, E+P-d],与真实内容重叠 ⟺ d > P - 56;而浮层可见 ⟺ d > 96。所以要让「浮层刚出现的那一刻」不压内容就得 P - 56 ≥ 96。152px 在 667px 高的手机上等于凭空吃掉一整行选项,且浮层只在读者已经主动向上滚过 96px 后才出现,所以按 CSS 注释记录理由后不做。本轮保证的是:贴底静止时(浮层隐藏)末条选项整行可点且与输入框有 28px 空隙;浮层可见时它浮在已滚上去的内容上,与两个聊天面一致,点一下即回到底。
未改浮层可见条件(任务书要求),也未把胶囊改回右对齐——tests/rectification-agentic-entry.test.ts 锁着 justify-content: center(BUG-478 的统一决策),右对齐是 2026-08-25 7a4360d8 的旧修法,已被取代,不擅自推翻。
4. 顺带发现的口径冲突(未擅自裁决,需产品拍板)
frontend/DESIGN.md §10 的「以下一律不得加回来」表里明确写着「已对照 N 件经历」不上条、仍归交付卡,理由是它和「已答 N 题」不是同一个量。但 cfb41daf(2026-09-16,BUG-740~743)把 datedEventLabel 加到了读数上,且没有改 DESIGN。也就是说这第五项从进条那天起就与 DESIGN 的红线矛盾,而它正是压垮 375px 宽度预算的那一项。
本轮只在 767px 以下把它移出可见行(任务书授权范围内),桌面保留原状,并把这处冲突写进 BUG-918 的「相关记录」、DESIGN §10 和真机清单,等产品决定桌面是否也撤掉。没有单方面改桌面。
5. 测试
新增 frontend/tests/rectification-mobile-timeline-readout-20260917.test.tsx(6 条):
- 渲染断言:五项文本按序全在 DOM,且轴
aria-label含全部五项。 - 宽度预算断言:compact 可见四项 + 3×8px ≤ 343px(375)与 ≤ 358px(390);并反向断言旧口径 383px > 255px,把 Bug 的形状钉住。
- compact 段声明断言:
padding-inline: var(--space-4)且段内不含--assistant-content-inset;column-gap: var(--space-2);__dateddisplay: none;段内不得出现__range/__width/__working(这两个数字任何宽度都不许隐藏或缩);不得放开flex-wrap/white-space;条高仍 56px。段的切取是按大括号配平取出那一个@media块,不是slice到文件尾。 - 桌面段断言:仍是
calc(var(--space-8) + var(--assistant-content-inset)),读数仍nowrap+ 13px。 - T2 断言:留白表达式、
scroll-padding-block-end。 - 浮层未动断言:
absolute/bottom: 100%/justify-content: center/pointer-events: none/ 按钮 44px,以及conversationAnchorThreshold = 96与 anchor hook 里不出现 scroll-padding。
文件头写明了「本套件没有 DOM 实现,所以几何断言是算术不是测量,真机走查必做」。
改写的既有断言 1 条 —— frontend/tests/rectification-timeline-20260909.test.ts「the mobile bar stays within the 44px touch rhythm」:
- 原值:
assert.match(mobile, /padding-inline: calc\(var\(--space-4\) \+ var\(--assistant-content-inset\)\);/) - 新值:
assert.match(mobile, /padding-inline: var\(--space-4\);/) - 原因:BUG-918。这条断言锁的正是造成裁切的那 44px 头像沟槽。条不在消息列里,手机上对齐头像列没有可见收益;同一测试里桌面那条 inset 断言未动,
--rectification-jump-clearance断言未动。
没有弱化其它任何断言,没有删测试。
6. 门禁数字
| 项 | 基线(c32f81e7) |
改后 |
|---|---|---|
./node_modules/.bin/tsc --noEmit |
— | 0 错 |
npm run lint |
— | 0 error(116 warning,与基线同为既有 no-unused-vars,未顺手修) |
npm test |
3414 tests / 31 fail | 3420 tests / 31 fail(+6 新测试全绿) |
| 失败清单 | 31 条无 Docker 集 | 逐条相同(排序后 diff 无输出) |
next build --webpack |
exit 0 | exit 0 |
/ 路由 |
○ Static |
○ Static |
| 首屏 gzip | 620,106 B / 25 文件 | 620,128 B / 25 文件(+22 B, +0.004%) |
- 失败清单 31 条全部是既有无 Docker / 无凭据集(database-*、staging sync、billing、ephemeris 401 等),与
BLOCKED.md一致。 - gzip 口径:把
.next/server/app/index.html里引用到的每个/_next/static/*.js|css单独gzip -9后求和。唯一变化是首屏 CSS 分块 36,510 → 36,532 B。 - Turbopack 拒绝软链
node_modules,按环境说明用--webpack。
7. 环境缺口
- 无 Chrome、无真机:375 / 390 宽下「读数四项完整」「胶囊不压选项」只能人工确认,清单在
docs/testing/rectification-mobile-timeline-readout-20260917.md(7 条 + 已知边界)。第 2 节的宽度是算术,不是真机测量;第 3 节的 28px 空隙同样没有真机截图。 - 未部署:本分支只推自己的分支,未推 staging,
deployment.gitCommit未核对。