fix(web): dismiss chat tooltips when scrolling - #7768
Conversation
Close hover-opened timeline tooltips when their trigger moves away under a stationary pointer. Preserve keyboard-focused tooltips and keep timeline tooltip portals below the composer.
|
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:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
UI consistency review: one layering issue found in the new tooltip content layer. The scroll-dismiss controller itself (tooltipScrollDismiss.ts) and the TooltipLayerProvider wiring in MessagesTimeline look consistent with the shared primitive contract; the concern is the z-index value chosen for the new layer.
Posted via Macroscope — UI Consistency
Treat focus on descendants of a rendered tooltip trigger as focus within the trigger so scrolling does not dismiss keyboard-accessible tooltips.
Remove the content-specific tooltip layer so scroll dismissal does not place timeline tooltips behind minimaps and floating controls. Keep the scroll path on a stable callback-only context.
Keep the hovered tooltip reference while focus remains within its trigger so a later scroll can dismiss it after focus moves away.
ApprovabilityVerdict: Approved at Macroscope's review found this PR approvable — Self-contained UI fix that dismisses tooltips when scrolling in the chat timeline. The implementation adds a simple tracking controller with proper React context integration and comprehensive test coverage. Low-risk, narrow scope change. You can add or adjust custom eligibility rules. Learn more. |
What Changed
Why
Scrolling moves message content without necessarily moving the pointer or emitting a mouseleave event. A tooltip could therefore remain open after its trigger had moved away, and its portal layer could paint over the composer.
The timeline now tracks only the current hover tooltip through a stable callback-only context. Scroll handling performs an O(1) lookup and imperative close without updating React state or context, avoiding a render fan-out on the scroll path.
Closes #7767.
UI Changes
Before: A tooltip opened over a message could remain visible while scrolling and overlap the composer.
After: Hover-opened timeline tooltips close on the first scroll event. Keyboard-focused tooltips remain available, and timeline tooltips retain their existing stacking above chat chrome.
A recording of the scroll interaction is attached below. Before/after screenshots are still outstanding, so the PR remains a draft.
Registrazione.schermo.2026-08-21.alle.10.38.03.mov
Testing
cd apps/web && pnpm exec vp test run src/components/ui/tooltip.test.tsx src/components/chat/MessagesTimeline.test.tsx --project unit— 33 passedcd apps/web && pnpm run typecheck— passedcd apps/web && pnpm exec vp build— passedChecklist
Implemented with GPT-5.6 Sol in the Codex harness via T3 Code.
Note
Low Risk
UI-only tooltip hover tracking and scroll close; no auth or data-path changes. TooltipTrigger now composes mouse handlers under the new provider.
Overview
Hover-opened tooltips in the chat timeline now close on scroll so they don’t stay parked over the composer after the trigger has moved.
MessagesTimelinewraps the list inTooltipScrollDismissProviderand callsdismissHoveredTooltip()fromonScroll. Dismissal is O(1) and imperative (no React state on the scroll path). Tooltips whose trigger (or a descendant) still has focus stay open.Outside the provider,
Tooltip/TooltipTriggerbehave as before. Tests cover one-shot dismiss, focus preservation, stacking (z-[140]), and that the timeline opts into the provider.Reviewed by Cursor Bugbot for commit 55de62b. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Dismiss hovered chat tooltips on scroll in
MessagesTimelineTooltipScrollDismissProvidercontext andcreateTooltipScrollDismissControllerso scroll handlers can programmatically close the currently hovered tooltip while preserving tooltips whose trigger or descendant has focus.MessagesTimelinewraps its timeline in the provider and callscontroller.dismissHoveredTooltip()at the start ofhandleScrollbefore updating scroll state.TooltipandTooltipTriggerparticipate only when rendered under the provider; outside it, behavior is unchanged.TooltipTriggernow wrapsonMouseEnter/onMouseLeavewhen inside a provider — verify any existing consumer-supplied handlers still fire correctly via tooltip.tsx.Macroscope summarized 55de62b.