fix(web): keep turn status visible while scrolling - #8667
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
There was a problem hiding this comment.
Reviewed the new pinned working-row overlay in MessagesTimeline.tsx for stacking and top-fade consistency. Two layering issues on the new overlay; the pin math and the list/overlay column geometry (px-3 sm:px-5 + mx-auto max-w-3xl) match the virtualized rows and look correct.
Posted via Macroscope — UI Consistency
ApprovabilityVerdict: Approved at Macroscope's review found this PR approvable — This is a focused web UI bug fix that keeps an existing turn-status row visible during scrolling. Its production impact is limited to localized overlay and responsive positioning logic, with targeted regression tests and no API, schema, configuration, or sensitive-area changes. You can add or adjust custom eligibility rules. Learn more. |
a7cda56 to
c6fa4f2
Compare
There was a problem hiding this comment.
One new finding on the pinned status-row overlay. The two points raised on the previous revision (overlay z-30 outranking the provider-status banner/composer overlays, and the unmasked top-0 copy negating the topbar-scroll-fade contract) still apply unchanged and are not re-posted here.
Posted via Macroscope — UI Consistency
There was a problem hiding this comment.
One finding on the pinned status-row overlay: making the copy interactive turns the band it covers into a scroll dead zone, because the overlay lives outside the list's scroll node.
Posted via Macroscope — UI Consistency
| {statusRowPinned && stickyStatusRow ? ( | ||
| <div | ||
| className="pointer-events-none absolute inset-x-0 z-10 px-3 sm:px-5" | ||
| data-turn-status-row-pinned="true" | ||
| style={{ top: statusRowTop }} | ||
| > | ||
| <div | ||
| aria-hidden={stickyStatusRow.kind === "working" || undefined} | ||
| className={cn( | ||
| "mx-auto w-full min-w-0 max-w-3xl overflow-x-clip bg-background", | ||
| stickyStatusRow.kind === "turn-fold" && "pointer-events-auto", |
There was a problem hiding this comment.
pointer-events-auto makes the pinned copy interactive, but this overlay is a sibling of LegendList, not a descendant of its scroll node — the element ChatView attaches wheel/touchmove to (getScrollableNode(), ChatView.tsx:4097/4172). A wheel event or touch drag whose target is this element has no scrollable ancestor, so while a completed turn is pinned the band it covers (full row width, at the top of the timeline) no longer scrolls the timeline at all. For the same reason it is a second focusable Worked for… button whenever the real row is still inside the virtualizer's render buffer.
Smallest durable fix: let the real row stick inside the scroller instead of duplicating it. @legendapp/list 3.3.5 supports this on web — stickyHeaderIndices={[rows.indexOf(stickyStatusRow)]} plus stickyHeaderConfig={{ offset: statusRowTop }} makes the actual row render position: sticky (PositionViewSticky), which drops the overlay, the duplicate control and the dead zone in one go. If that doesn't compose with the anchoring/maintainScrollAtEnd setup here, keep the copy decorative (pointer-events-none + aria-hidden for both kinds) so the real row stays the only fold control.
Posted via Macroscope — UI Consistency
The active turn status could scroll out of view because the old code assumed it was always the last timeline row. Once agent output followed it, that assumption was wrong.
This finds the status row by its stable list key and pins it only after it crosses the timeline header. It supports both the live
Working for… · current taskrow and the completedWorked for…row. Scrolling back returns it to its normal place.The live pinned copy is decorative and hidden from accessibility tools. The completed pinned row stays an accessible, clickable button. The overlay also follows the timeline fade offset and stays below banners and the composer.
Evidence
In place
Pinned
Scroll motion
sticky-turn-status.webm
Verification
pnpm exec vitest run apps/web/src/components/chat/MessagesTimeline.test.tsx— 40 tests passedpnpm --filter @t3tools/web typecheckpassedRisk is low. The change is limited to the web timeline status row and its focused regression check.
Generated with GPT-5.6 in the Codex harness.