docs(notes): record the hero glow removal, consolidating the one-axis-scroll note

The 2026-08-04 bug-fix note owned the overflow-x clip that existed only
for the glow's bleed; with the glow, the clip, and its test all gone the
note is fully superseded. The new note preserves its rationale and the
reintroduction condition for future bleeding chrome.
This commit is contained in:
Yif committed 2026-08-28 14:12:33 +08:00
1 parent d461922627
commit 5156226cb9
5 files changed
+61 -77

No files matched your search

@@ -1,37 +0,0 @@
# Agent Note: The conversation column scrolls on one axis
Status: implemented
English | [中文](2026-08-04-conversation-column-one-axis-scroll.zh.md)
## Problem
Narrowing the center column — by the window or by the sidebar drag — put a horizontal scrollbar under the whole conversation column on the hero. The bleeding element is the hero's decorative backdrop ellipse: `.heroGlow` is sized `1051/776` of the hero box so its blur scales in userSpace with the input card, which means it reaches past the column whenever the column is narrower than the glow.
That bleed is by construction and stays. What made it user-visible is the scroll container it sits in. `[data-conversation-scroll]` declared `overflow-y: auto` and left the other axis at its initial `visible`, and a box that scrolls in one axis computes `visible` to `auto` in the other. Every column narrower than the glow therefore offered a real horizontal scroll range — measured at 24–95px across the widths a laptop actually produces.
## Decision
`.scrollBody` declares `overflow-x: hidden`. The column states that it is a one-axis scroller instead of leaving the second axis to be derived.
Clipping does not change. `overflow-y: auto` had already made the box a scroll container that clips both axes, so the declaration withdraws only the scrollbar and the user gesture; the glow keeps its bleed, its blur radius, and the same painted extent, and the column keeps its vertical scroll. Nothing in the composer chain moves.
## Alternatives considered
**Size the glow to fit the column.** Rejected. The glow's width is what scales its `stdDeviation="50"` blur with the input card (figma 313:14109); constraining it would make the blur tighten as the column narrows, which is a visual regression to fix a scrollbar.
**Wrap the glow in a clipping box.** Rejected. It adds a box whose only job is to undo an overflow the column already clips, and it leaves the derived `overflow-x: auto` in place for the next element that bleeds — the transcript is full of candidates.
**Rely on the frame's `.centerCol { overflow: hidden }`.** It cannot help. That clip is outside the scroll container, so it hides the glow's overhang at the column border while the container inside it still scrolls to reach it. The reported bar was that container's.
**Assert `scrollWidth === clientWidth` in the test.** Rejected as the signal, because it does not distinguish the states: `hidden` clips the bleed rather than reflowing it away, so the scroll range reads the same on both sides of the fix. Only refusing a user gesture differs, which is what the scenario measures.
## Testing
[apps/web/tests/conversation-column-overflow.e2e.ts](../../../../apps/web/tests/conversation-column-overflow.e2e.ts) sweeps viewport widths bracketing the glow and, at each stop, wheels horizontally over the column and reads `scrollLeft`. The committed golden records the relation per stop; the widest stop is the control where the glow does not bleed at all.
Two guards keep the scenario honest. The vacuity guard asserts the glow still reaches past the column at the narrow stops, so the claim cannot pass by the symptom having disappeared for an unrelated reason. The mutation control forces `overflow-x: auto` back on in the page and shows the same gesture, at the same timing, carrying the column to its positive scroll boundary; the test measures that boundary directly because a stable scrollbar gutter can leave some overflow on the negative side of the scroll origin. Without the control, a `scrollLeft` of 0 could equally mean the wheel never arrived.
## Consequences
The conversation column no longer offers a horizontal scrollbar at any width, and decorative bleed in the composer chain is now clipped rather than exposed as scroll range. The cost is that genuinely wide content under this column is clipped instead of reachable by scrolling: any such surface owns its own scroller, as the markdown code block and the trajectory table already do.
@@ -1,37 +0,0 @@
# Agent Note: 会话列只在一个轴上滚动
Status: implemented
[English](2026-08-04-conversation-column-one-axis-scroll.md) | 中文
## 问题
当中间列被拉窄——无论是拖窗口还是拖侧边栏——hero 态的整条会话列下方就会出现一条横向滚动条。溢出的元素是 hero 的装饰性背景椭圆:`.heroGlow` 的宽度取 hero 盒子的 `1051/776`,好让它的模糊在 userSpace 中随输入卡片一同缩放;这也意味着只要列比它窄,它就会伸出列外。
这处外溢是设计使然,保持不变。真正让它对用户可见的是它所处的滚动容器。`[data-conversation-scroll]` 只声明了 `overflow-y: auto`,另一个轴留在初始值 `visible`;而一个在某一轴上滚动的盒子,会把另一轴的 `visible` 计算为 `auto`。于是每一条比该椭圆窄的列都真的给出了一段横向滚动范围——在笔记本实际会产生的几档宽度上,实测为 24–95px。
## 决策
`.scrollBody` 声明 `overflow-x: hidden`。这条列明确声明自己是单轴滚动容器,而不是把第二个轴交给推导。
裁剪行为不变。`overflow-y: auto` 早已使该盒子成为在两个轴上都裁剪的滚动容器,因此这条声明收回的只是滚动条和用户手势;椭圆保留它的外溢、模糊半径和同样的绘制范围,列也保留纵向滚动。输入区那条链路上没有任何东西移动。
## 曾考虑的替代方案
**把椭圆缩到列内。** 否决。椭圆的宽度正是让它 `stdDeviation="50"` 的模糊随输入卡片缩放的依据(figma 313:14109);约束宽度会使列越窄模糊越紧,等于为修一条滚动条而制造一处视觉回归。
**给椭圆套一层裁剪盒。** 否决。这层盒子唯一的职责是抵消列本就会裁剪的溢出,而推导出的 `overflow-x: auto` 仍然留在原处,等着下一个外溢的元素——transcript(文本记录)里这样的候选者不少。
**依赖外框的 `.centerCol { overflow: hidden }`。** 它帮不上忙。那处裁剪在滚动容器之外,只能在列边界处遮住椭圆探出的部分,而里面的容器照样可以滚过去够到它。用户报告的那条滚动条属于内层容器。
**在测试里断言 `scrollWidth === clientWidth`。** 作为判据被否决,因为它区分不出两种状态:`hidden` 裁剪外溢,而不是把它重排掉,所以修复前后读到的滚动范围一样。唯一有差别的是拒绝用户手势,这正是该场景所测量的。
## 测试
[apps/web/tests/conversation-column-overflow.e2e.ts](../../../../apps/web/tests/conversation-column-overflow.e2e.ts) 扫过一组把椭圆宽度夹在中间的视口宽度,在每一档上于列上触发横向滚轮事件并读取 `scrollLeft`。提交的 golden 逐档记录该关系;最宽的一档是椭圆根本不外溢的对照。
两道防线保证该场景不流于形式。空断言防线断言窄档上椭圆确实仍伸出列外,使这项主张不可能因为症状出于无关原因消失而通过。变异对照则在页面内把 `overflow-x: auto` 强制改回,证明同一手势在同一时序下能把列带到正向滚动边界。测试直接测量该边界,因为稳定的滚动条槽可能让部分外溢处于滚动原点的负向。没有这项对照,`scrollLeft` 读到 0 同样可以解释为滚轮事件根本没送达。
## 后果
会话列在任何宽度下都不再给出横向滚动条,输入区链路上的装饰性外溢从暴露为滚动范围改为被裁剪。代价是这条列下真正过宽的内容会被裁掉而非可滚动够到:这类界面各自拥有自己的滚动容器,markdown 代码块和轨迹表格已经如此。
@@ -1,6 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/bug-fix/2026-08-04-conversation-column-one-axis-scroll.md
2026-08-04-conversation-column-one-axis-scroll.md: 9a487c506a75033d0854f08e95da24704309003d
2026-08-04-conversation-column-one-axis-scroll.zh.md: b86f86f55757dff4fddab4c4e2ac64fa7c19fe59
# pnpm run verify-translation-pairing --write .agents/notes/implemented/simplification/2026-08-28-remove-hero-input-glow.md
2026-08-28-remove-hero-input-glow.md: 929fce91d38ed5436421e91666e91328389a1302
2026-08-28-remove-hero-input-glow.zh.md: e8a32c8dc60feae344be587e4bcc4b8a4f8a2d87
@@ -0,0 +1,29 @@
# Agent Note: The hero input glow is removed
Status: implemented
English | [中文](2026-08-28-remove-hero-input-glow.zh.md)
## Problem
The New Session hero painted a decorative backdrop ellipse (`HeroGlow`, figma 313:14109) under the input card: a blurred blue gradient sized `1051/776` of the hero box so its `stdDeviation="50"` blur scaled with the card. On the shipped token sheets the ellipse read as stray blue tint rather than intentional chrome, and its by-construction bleed past the conversation column forced clipping scaffolding onto the column itself.
That scaffolding existed because a box that scrolls in one axis computes the other axis's initial `visible` to `auto`: the glow's overhang gave `[data-conversation-scroll]` a real 24–95px horizontal scroll range on laptop widths, patched by declaring `overflow-x: hidden` on `.scrollBody` (2026-08-04). This note supersedes and consolidates that bug-fix note.
## Decision
`HeroGlow` is deleted with its positioning scaffolding: the component and its seat in `EmptyHero.tsx`, the glow z-index carve-outs in `ConversationRoot.module.css`, and the `.scrollBody { overflow-x: hidden }` clip, which had no owner other than the glow's bleed. The scroll body's horizontal axis returns to its derived value, and nothing under the column currently bleeds past it.
The e2e scenario `conversation-column-overflow.e2e.ts` and its golden are deleted with the glow: the test's vacuity guard asserted the glow still bled past the column at narrow stops, so it cannot pass — by design — once nothing bleeds.
## Alternatives considered
**Keep the glow and retune its color.** Rejected. The tint was not a token mistake to correct; the product read is that the homepage input carries no backdrop chrome at all.
**Keep `overflow-x: hidden` as a defensive clip.** Rejected. With the glow gone the declaration has no current owner, and the repo requires one; a silent clip would also hide the next accidental bleed instead of surfacing it in review.
**Keep the overflow test against future bleed.** Rejected. Its vacuity guard requires a presently-bleeding element, so the scenario cannot express "nothing bleeds" without inverting into a different test; the composer geometry golden already pins the scroll body's `overflow` axes per tab.
## Consequences
The hero stack is plain chrome above the shared input card, and 67 lines of glow component, seat wiring, and clip scaffolding are gone. The cost is the standing guard: the conversation column is again a one-axis scroller only by construction, so a future decorative element that bleeds past the column will re-derive `overflow-x: auto` and surface a horizontal scrollbar. Whoever reintroduces bleed must restore an explicit one-axis clip on `.scrollBody` and a gesture-level regression test — asserting `scrollWidth === clientWidth` is not a substitute, because a clip hides the range without reflowing it away and only the refused wheel gesture distinguishes the states. The composer tab geometry golden records the current `overflow auto/auto` reading and will flag the derivation flipping back.
@@ -0,0 +1,29 @@
# Agent Note: The hero input glow is removed
Status: implemented
[English](2026-08-28-remove-hero-input-glow.md) | 中文
## Problem
New Session 首页曾在输入卡片下方绘制一个装饰性背景椭圆(`HeroGlow`,figma 313:14109):一个模糊的蓝色渐变,尺寸为 hero 盒子的 `1051/776`,使其 `stdDeviation="50"` 模糊随卡片缩放。在实际交付的 token 表下,这个椭圆看起来是意外的蓝色沾染而非有意的装饰,并且它按构造就会溢出会话列,迫使列本身背上裁剪脚手架。
脚手架的由来:单轴滚动的盒子会把另一轴初始的 `visible` 推导为 `auto`,glow 的溢出让 `[data-conversation-scroll]` 在笔记本宽度下出现 24–95px 的真实横向滚动范围,当时(2026-08-04)靠在 `.scrollBody` 上声明 `overflow-x: hidden` 修补。本 note 取代并合并了那个 bug-fix note。
## Decision
`HeroGlow` 连同其定位脚手架一并删除:组件本体及其在 `EmptyHero.tsx` 中的座位、`ConversationRoot.module.css` 中为 glow 开的 z-index 例外,以及 `.scrollBody { overflow-x: hidden }` 裁剪——后者除 glow 的溢出外没有任何持有者。滚动主体的横轴回到推导值,当前列下没有任何元素溢出。
e2e 场景 `conversation-column-overflow.e2e.ts` 及其 golden 随 glow 一并删除:该测试的空洞防护(vacuity guard)断言 glow 在窄档位仍然溢出列,因此一旦没有任何东西溢出,它按设计就无法通过。
## Alternatives considered
**保留 glow 只调整颜色。** 拒绝。这不是一个待修正的 token 错误;产品判断是首页输入卡片根本不应携带背景装饰。
**保留 `overflow-x: hidden` 作为防御性裁剪。** 拒绝。glow 删除后该声明没有当前持有者,而仓库要求每项内容都有;静默裁剪还会把下一次意外溢出藏起来,而不是在评审中暴露它。
**保留 overflow 测试防范未来溢出。** 拒绝。它的空洞防护要求当下存在一个正在溢出的元素,场景无法在不改写成另一个测试的前提下表达"没有东西溢出";composer 几何 golden 已经按 tab 钉住了滚动主体的 `overflow` 两轴取值。
## Consequences
hero 栈成为共享输入卡片上方的朴素装饰,glow 组件、座位接线和裁剪脚手架共 67 行被删除。代价是失去常驻防线:会话列重新只靠构造保持单轴滚动,未来任何溢出列的装饰元素都会重新推导出 `overflow-x: auto` 并出现横向滚动条。重新引入溢出者必须在 `.scrollBody` 上恢复显式单轴裁剪并补上手势级回归测试——断言 `scrollWidth === clientWidth` 不能替代,因为裁剪只是隐藏范围而非将其回流消除,只有被拒绝的滚轮手势能区分两种状态。composer tab 几何 golden 记录了当前 `overflow auto/auto` 的读数,推导翻转回去时会报警。