Skip to content

Commit 17d2f71

Browse files
committed
🤖 fix: remove review line tooltip
Stop rendering the floating review comment helper from the review gutter so hovering line controls no longer obscures nearby code while keeping inline comment actions and range selection intact. --- _Generated with `mux` • Model: `openai:gpt-5.4` • Thinking: `xhigh` • Cost: `$0.92`_ <!-- mux-attribution: model=openai:gpt-5.4 thinking=xhigh costs=0.92 -->
1 parent 3cec659 commit 17d2f71

2 files changed

Lines changed: 7 additions & 119 deletions

File tree

src/browser/features/Shared/DiffRenderer.tsx

Lines changed: 3 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,11 @@
55
*/
66

77
import React, { useEffect, useMemo, useState } from "react";
8-
import { createPortal } from "react-dom";
98
import { stopKeyboardPropagation } from "@/browser/utils/events";
109
import { cn } from "@/common/lib/utils";
1110
import { getLanguageFromPath } from "@/common/utils/git/languageDetector";
1211
import { useOverflowDetection } from "@/browser/hooks/useOverflowDetection";
1312
import { MessageSquare } from "lucide-react";
14-
import { TOOLTIP_SURFACE_CLASSNAME } from "@/browser/components/Tooltip/Tooltip";
1513
import { InlineReviewNote, type ReviewActionCallbacks } from "./InlineReviewNote";
1614
import { groupDiffLines } from "@/browser/utils/highlighting/diffChunking";
1715
import { useTheme, type ThemeMode } from "@/browser/contexts/ThemeContext";
@@ -672,15 +670,6 @@ interface LineSelection {
672670
endIndex: number;
673671
}
674672

675-
interface TooltipAnchorRect {
676-
left: number;
677-
top: number;
678-
width: number;
679-
height: number;
680-
}
681-
682-
const REVIEW_COMMENT_TOOLTIP = "Add review comment (Shift-click or drag to select range)";
683-
684673
// CSS class for diff line wrapper - used by arbitrary selector in CommentButton
685674
const SELECTABLE_DIFF_LINE_CLASS = "selectable-diff-line";
686675

@@ -1029,49 +1018,6 @@ export const SelectableDiffRenderer = React.memo<SelectableDiffRendererProps>(
10291018
const [selection, setSelection] = React.useState<LineSelection | null>(null);
10301019
const [selectionInitialNoteText, setSelectionInitialNoteText] = React.useState("");
10311020

1032-
const reviewTooltipTriggerRef = React.useRef<HTMLButtonElement | null>(null);
1033-
const [reviewTooltipAnchorRect, setReviewTooltipAnchorRect] =
1034-
React.useState<TooltipAnchorRect | null>(null);
1035-
1036-
const hideReviewTooltip = React.useCallback((trigger?: HTMLButtonElement | null) => {
1037-
if (trigger && reviewTooltipTriggerRef.current !== trigger) {
1038-
return;
1039-
}
1040-
1041-
reviewTooltipTriggerRef.current = null;
1042-
setReviewTooltipAnchorRect(null);
1043-
}, []);
1044-
1045-
const syncReviewTooltipAnchor = React.useCallback(() => {
1046-
const trigger = reviewTooltipTriggerRef.current;
1047-
if (!trigger?.isConnected) {
1048-
hideReviewTooltip();
1049-
return;
1050-
}
1051-
1052-
const { left, top, width, height } = trigger.getBoundingClientRect();
1053-
setReviewTooltipAnchorRect((previousRect) => {
1054-
if (
1055-
previousRect?.left === left &&
1056-
previousRect?.top === top &&
1057-
previousRect?.width === width &&
1058-
previousRect?.height === height
1059-
) {
1060-
return previousRect;
1061-
}
1062-
1063-
return { left, top, width, height };
1064-
});
1065-
}, [hideReviewTooltip]);
1066-
1067-
const showReviewTooltip = React.useCallback(
1068-
(trigger: HTMLButtonElement) => {
1069-
reviewTooltipTriggerRef.current = trigger;
1070-
syncReviewTooltipAnchor();
1071-
},
1072-
[syncReviewTooltipAnchor]
1073-
);
1074-
10751021
const flushPendingDragSelection = React.useCallback(() => {
10761022
const anchorIndex = dragAnchorRef.current;
10771023
const pendingLineIndex = pendingDragLineIndexRef.current;
@@ -1139,34 +1085,6 @@ export const SelectableDiffRenderer = React.memo<SelectableDiffRendererProps>(
11391085
};
11401086
}, []);
11411087

1142-
React.useEffect(() => {
1143-
if (!reviewTooltipAnchorRect) {
1144-
return;
1145-
}
1146-
1147-
const handleViewportChange = () => {
1148-
syncReviewTooltipAnchor();
1149-
};
1150-
1151-
window.addEventListener("resize", handleViewportChange);
1152-
window.addEventListener("scroll", handleViewportChange, true);
1153-
1154-
return () => {
1155-
window.removeEventListener("resize", handleViewportChange);
1156-
window.removeEventListener("scroll", handleViewportChange, true);
1157-
};
1158-
}, [reviewTooltipAnchorRect, syncReviewTooltipAnchor]);
1159-
1160-
React.useEffect(() => {
1161-
if (!reviewTooltipTriggerRef.current) {
1162-
return;
1163-
}
1164-
1165-
// File/hunk switches can remove the hovered trigger during a normal React render without any
1166-
// scroll/resize event, so resync here too to avoid leaving a stale floating tooltip behind.
1167-
syncReviewTooltipAnchor();
1168-
});
1169-
11701088
const { theme } = useTheme();
11711089

11721090
const lastExternalSelectionRequestIdRef = React.useRef<number | null>(null);
@@ -1368,8 +1286,6 @@ export const SelectableDiffRenderer = React.memo<SelectableDiffRendererProps>(
13681286
return;
13691287
}
13701288

1371-
hideReviewTooltip();
1372-
13731289
// Notify parent that this hunk should become active.
13741290
onLineClick?.();
13751291
onLineIndexSelect?.(lineIndex, shiftKey);
@@ -1396,7 +1312,7 @@ export const SelectableDiffRenderer = React.memo<SelectableDiffRendererProps>(
13961312
return { startIndex: anchor, endIndex: lineIndex };
13971313
});
13981314
},
1399-
[hideReviewTooltip, onLineClick, onLineIndexSelect, onReviewNote, renderSelectionStartIndex]
1315+
[onLineClick, onLineIndexSelect, onReviewNote, renderSelectionStartIndex]
14001316
);
14011317

14021318
const updateDragSelection = React.useCallback(
@@ -1413,8 +1329,6 @@ export const SelectableDiffRenderer = React.memo<SelectableDiffRendererProps>(
14131329
);
14141330

14151331
const handleCommentButtonClick = (lineIndex: number, shiftKey: boolean) => {
1416-
hideReviewTooltip();
1417-
14181332
// Keep immersive cursor/hunk selection in sync with inline comment actions.
14191333
onLineClick?.();
14201334
onLineIndexSelect?.(lineIndex, shiftKey);
@@ -1573,17 +1487,12 @@ export const SelectableDiffRenderer = React.memo<SelectableDiffRendererProps>(
15731487
reviewButton={
15741488
onReviewNote && (
15751489
<>
1576-
{/* Regular review can mount thousands of diff lines at once, so keep
1577-
one shared tooltip anchored to the active button instead of mounting
1578-
a full Radix tooltip tree for every individual line. */}
1490+
{/* Review mode already turns the gutter into a hover target, so keep the
1491+
action inline without an extra floating tooltip covering nearby lines. */}
15791492
<button
15801493
type="button"
15811494
className="pointer-events-none absolute inset-0 flex items-center justify-center rounded-sm text-[var(--color-review-accent)]/60 opacity-0 transition-opacity group-hover:pointer-events-auto group-hover:opacity-100 hover:text-[var(--color-review-accent)] active:scale-90"
15821495
style={{ position: "absolute", inset: 0 }}
1583-
onMouseEnter={(event) => showReviewTooltip(event.currentTarget)}
1584-
onMouseLeave={(event) => hideReviewTooltip(event.currentTarget)}
1585-
onFocus={(event) => showReviewTooltip(event.currentTarget)}
1586-
onBlur={(event) => hideReviewTooltip(event.currentTarget)}
15871496
onClick={(e) => {
15881497
e.stopPropagation();
15891498
handleCommentButtonClick(displayIndex, e.shiftKey);
@@ -1645,25 +1554,6 @@ export const SelectableDiffRenderer = React.memo<SelectableDiffRendererProps>(
16451554
);
16461555
})}
16471556
</DiffContainer>
1648-
{reviewTooltipAnchorRect &&
1649-
createPortal(
1650-
<div
1651-
className={cn(
1652-
TOOLTIP_SURFACE_CLASSNAME,
1653-
"pointer-events-none fixed z-[10001] border-separator-light"
1654-
)}
1655-
style={{
1656-
left: reviewTooltipAnchorRect.left + reviewTooltipAnchorRect.width + 8,
1657-
top: reviewTooltipAnchorRect.top + reviewTooltipAnchorRect.height / 2,
1658-
maxWidth: "min(20rem, calc(100vw - 24px))",
1659-
transform: "translateY(-50%)",
1660-
}}
1661-
>
1662-
<span className="border-border-medium bg-modal-bg absolute top-1/2 left-0 h-2 w-2 -translate-x-1/2 -translate-y-1/2 rotate-45 border-b border-l" />
1663-
{REVIEW_COMMENT_TOOLTIP}
1664-
</div>,
1665-
document.body
1666-
)}
16671557
</>
16681558
);
16691559
}

src/browser/features/Shared/SelectableDiffRenderer.dragSelect.test.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ describe("SelectableDiffRenderer drag selection", () => {
103103
}
104104
});
105105

106-
test("hovering the review button uses the full custom range-selection tooltip", async () => {
106+
test("hovering the review button does not show a tooltip", async () => {
107107
const content = "+const a = 1;\n+const b = 2;";
108108

109109
const { container } = render(
@@ -128,11 +128,9 @@ describe("SelectableDiffRenderer drag selection", () => {
128128

129129
fireEvent.mouseEnter(commentButton!);
130130

131-
await waitFor(() => {
132-
expect(document.body.textContent).toContain(
133-
"Add review comment (Shift-click or drag to select range)"
134-
);
135-
});
131+
expect(document.body.textContent).not.toContain(
132+
"Add review comment (Shift-click or drag to select range)"
133+
);
136134
});
137135

138136
test("dragging on the indicator column selects a line range", async () => {

0 commit comments

Comments
 (0)