From 85f35be75e7978e678921467c6ffb75b07ed1f0c Mon Sep 17 00:00:00 2001 From: Ammar Date: Sun, 29 Mar 2026 16:22:38 -0500 Subject: [PATCH] =?UTF-8?q?=F0=9F=A4=96=20fix:=20remove=20review=20line=20?= =?UTF-8?q?tooltip?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stop rendering the floating review comment helper from the shared review diff renderer so hovering the gutter action no longer obscures nearby code. The shared renderer also powers both review panes, so the follow-up comment now calls out that scope directly while preserving the inline review action and range selection behavior. --- _Generated with `mux` • Model: `openai:gpt-5.4` • Thinking: `xhigh` • Cost: `$1.93`_ --- src/browser/features/Shared/DiffRenderer.tsx | 120 +----------------- ...SelectableDiffRenderer.dragSelect.test.tsx | 10 +- 2 files changed, 10 insertions(+), 120 deletions(-) diff --git a/src/browser/features/Shared/DiffRenderer.tsx b/src/browser/features/Shared/DiffRenderer.tsx index 05fcdb3c9f..d0846f67d7 100644 --- a/src/browser/features/Shared/DiffRenderer.tsx +++ b/src/browser/features/Shared/DiffRenderer.tsx @@ -1,17 +1,16 @@ /** * DiffRenderer - Shared diff rendering component * Used by FileEditToolCall for read-only diff display. - * ReviewPanel uses SelectableDiffRenderer for interactive line selection. + * ReviewPanel and ImmersiveReviewView both use SelectableDiffRenderer for + * interactive line selection. */ import React, { useEffect, useMemo, useState } from "react"; -import { createPortal } from "react-dom"; import { stopKeyboardPropagation } from "@/browser/utils/events"; import { cn } from "@/common/lib/utils"; import { getLanguageFromPath } from "@/common/utils/git/languageDetector"; import { useOverflowDetection } from "@/browser/hooks/useOverflowDetection"; import { MessageSquare } from "lucide-react"; -import { TOOLTIP_SURFACE_CLASSNAME } from "@/browser/components/Tooltip/Tooltip"; import { InlineReviewNote, type ReviewActionCallbacks } from "./InlineReviewNote"; import { groupDiffLines } from "@/browser/utils/highlighting/diffChunking"; import { useTheme, type ThemeMode } from "@/browser/contexts/ThemeContext"; @@ -672,15 +671,6 @@ interface LineSelection { endIndex: number; } -interface TooltipAnchorRect { - left: number; - top: number; - width: number; - height: number; -} - -const REVIEW_COMMENT_TOOLTIP = "Add review comment (Shift-click or drag to select range)"; - // CSS class for diff line wrapper - used by arbitrary selector in CommentButton const SELECTABLE_DIFF_LINE_CLASS = "selectable-diff-line"; @@ -1029,49 +1019,6 @@ export const SelectableDiffRenderer = React.memo( const [selection, setSelection] = React.useState(null); const [selectionInitialNoteText, setSelectionInitialNoteText] = React.useState(""); - const reviewTooltipTriggerRef = React.useRef(null); - const [reviewTooltipAnchorRect, setReviewTooltipAnchorRect] = - React.useState(null); - - const hideReviewTooltip = React.useCallback((trigger?: HTMLButtonElement | null) => { - if (trigger && reviewTooltipTriggerRef.current !== trigger) { - return; - } - - reviewTooltipTriggerRef.current = null; - setReviewTooltipAnchorRect(null); - }, []); - - const syncReviewTooltipAnchor = React.useCallback(() => { - const trigger = reviewTooltipTriggerRef.current; - if (!trigger?.isConnected) { - hideReviewTooltip(); - return; - } - - const { left, top, width, height } = trigger.getBoundingClientRect(); - setReviewTooltipAnchorRect((previousRect) => { - if ( - previousRect?.left === left && - previousRect?.top === top && - previousRect?.width === width && - previousRect?.height === height - ) { - return previousRect; - } - - return { left, top, width, height }; - }); - }, [hideReviewTooltip]); - - const showReviewTooltip = React.useCallback( - (trigger: HTMLButtonElement) => { - reviewTooltipTriggerRef.current = trigger; - syncReviewTooltipAnchor(); - }, - [syncReviewTooltipAnchor] - ); - const flushPendingDragSelection = React.useCallback(() => { const anchorIndex = dragAnchorRef.current; const pendingLineIndex = pendingDragLineIndexRef.current; @@ -1139,34 +1086,6 @@ export const SelectableDiffRenderer = React.memo( }; }, []); - React.useEffect(() => { - if (!reviewTooltipAnchorRect) { - return; - } - - const handleViewportChange = () => { - syncReviewTooltipAnchor(); - }; - - window.addEventListener("resize", handleViewportChange); - window.addEventListener("scroll", handleViewportChange, true); - - return () => { - window.removeEventListener("resize", handleViewportChange); - window.removeEventListener("scroll", handleViewportChange, true); - }; - }, [reviewTooltipAnchorRect, syncReviewTooltipAnchor]); - - React.useEffect(() => { - if (!reviewTooltipTriggerRef.current) { - return; - } - - // File/hunk switches can remove the hovered trigger during a normal React render without any - // scroll/resize event, so resync here too to avoid leaving a stale floating tooltip behind. - syncReviewTooltipAnchor(); - }); - const { theme } = useTheme(); const lastExternalSelectionRequestIdRef = React.useRef(null); @@ -1368,8 +1287,6 @@ export const SelectableDiffRenderer = React.memo( return; } - hideReviewTooltip(); - // Notify parent that this hunk should become active. onLineClick?.(); onLineIndexSelect?.(lineIndex, shiftKey); @@ -1396,7 +1313,7 @@ export const SelectableDiffRenderer = React.memo( return { startIndex: anchor, endIndex: lineIndex }; }); }, - [hideReviewTooltip, onLineClick, onLineIndexSelect, onReviewNote, renderSelectionStartIndex] + [onLineClick, onLineIndexSelect, onReviewNote, renderSelectionStartIndex] ); const updateDragSelection = React.useCallback( @@ -1413,8 +1330,6 @@ export const SelectableDiffRenderer = React.memo( ); const handleCommentButtonClick = (lineIndex: number, shiftKey: boolean) => { - hideReviewTooltip(); - // Keep immersive cursor/hunk selection in sync with inline comment actions. onLineClick?.(); onLineIndexSelect?.(lineIndex, shiftKey); @@ -1573,17 +1488,13 @@ export const SelectableDiffRenderer = React.memo( reviewButton={ onReviewNote && ( <> - {/* Regular review can mount thousands of diff lines at once, so keep - one shared tooltip anchored to the active button instead of mounting - a full Radix tooltip tree for every individual line. */} + {/* Both review panes share SelectableDiffRenderer, so keep the + review action inline without an extra floating tooltip + covering nearby lines. */}