11/**
22 * DiffRenderer - Shared diff rendering component
33 * Used by FileEditToolCall for read-only diff display.
4- * ReviewPanel uses SelectableDiffRenderer for interactive line selection.
4+ * ReviewPanel and ImmersiveReviewView both use SelectableDiffRenderer for
5+ * interactive line selection.
56 */
67
78import React , { useEffect , useMemo , useState } from "react" ;
8- import { createPortal } from "react-dom" ;
99import { stopKeyboardPropagation } from "@/browser/utils/events" ;
1010import { cn } from "@/common/lib/utils" ;
1111import { getLanguageFromPath } from "@/common/utils/git/languageDetector" ;
1212import { useOverflowDetection } from "@/browser/hooks/useOverflowDetection" ;
1313import { MessageSquare } from "lucide-react" ;
14- import { TOOLTIP_SURFACE_CLASSNAME } from "@/browser/components/Tooltip/Tooltip" ;
1514import { InlineReviewNote , type ReviewActionCallbacks } from "./InlineReviewNote" ;
1615import { groupDiffLines } from "@/browser/utils/highlighting/diffChunking" ;
1716import { useTheme , type ThemeMode } from "@/browser/contexts/ThemeContext" ;
@@ -672,15 +671,6 @@ interface LineSelection {
672671 endIndex : number ;
673672}
674673
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-
684674// CSS class for diff line wrapper - used by arbitrary selector in CommentButton
685675const SELECTABLE_DIFF_LINE_CLASS = "selectable-diff-line" ;
686676
@@ -1029,49 +1019,6 @@ export const SelectableDiffRenderer = React.memo<SelectableDiffRendererProps>(
10291019 const [ selection , setSelection ] = React . useState < LineSelection | null > ( null ) ;
10301020 const [ selectionInitialNoteText , setSelectionInitialNoteText ] = React . useState ( "" ) ;
10311021
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-
10751022 const flushPendingDragSelection = React . useCallback ( ( ) => {
10761023 const anchorIndex = dragAnchorRef . current ;
10771024 const pendingLineIndex = pendingDragLineIndexRef . current ;
@@ -1139,34 +1086,6 @@ export const SelectableDiffRenderer = React.memo<SelectableDiffRendererProps>(
11391086 } ;
11401087 } , [ ] ) ;
11411088
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-
11701089 const { theme } = useTheme ( ) ;
11711090
11721091 const lastExternalSelectionRequestIdRef = React . useRef < number | null > ( null ) ;
@@ -1368,8 +1287,6 @@ export const SelectableDiffRenderer = React.memo<SelectableDiffRendererProps>(
13681287 return ;
13691288 }
13701289
1371- hideReviewTooltip ( ) ;
1372-
13731290 // Notify parent that this hunk should become active.
13741291 onLineClick ?.( ) ;
13751292 onLineIndexSelect ?.( lineIndex , shiftKey ) ;
@@ -1396,7 +1313,7 @@ export const SelectableDiffRenderer = React.memo<SelectableDiffRendererProps>(
13961313 return { startIndex : anchor , endIndex : lineIndex } ;
13971314 } ) ;
13981315 } ,
1399- [ hideReviewTooltip , onLineClick , onLineIndexSelect , onReviewNote , renderSelectionStartIndex ]
1316+ [ onLineClick , onLineIndexSelect , onReviewNote , renderSelectionStartIndex ]
14001317 ) ;
14011318
14021319 const updateDragSelection = React . useCallback (
@@ -1413,8 +1330,6 @@ export const SelectableDiffRenderer = React.memo<SelectableDiffRendererProps>(
14131330 ) ;
14141331
14151332 const handleCommentButtonClick = ( lineIndex : number , shiftKey : boolean ) => {
1416- hideReviewTooltip ( ) ;
1417-
14181333 // Keep immersive cursor/hunk selection in sync with inline comment actions.
14191334 onLineClick ?.( ) ;
14201335 onLineIndexSelect ?.( lineIndex , shiftKey ) ;
@@ -1573,17 +1488,13 @@ export const SelectableDiffRenderer = React.memo<SelectableDiffRendererProps>(
15731488 reviewButton = {
15741489 onReviewNote && (
15751490 < >
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 . */ }
1491+ { /* Both review panes share SelectableDiffRenderer , so keep the
1492+ review action inline without an extra floating tooltip
1493+ covering nearby lines . */ }
15791494 < button
15801495 type = "button"
15811496 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"
15821497 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 ) }
15871498 onClick = { ( e ) => {
15881499 e . stopPropagation ( ) ;
15891500 handleCommentButtonClick ( displayIndex , e . shiftKey ) ;
@@ -1645,25 +1556,6 @@ export const SelectableDiffRenderer = React.memo<SelectableDiffRendererProps>(
16451556 ) ;
16461557 } ) }
16471558 </ 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- ) }
16671559 </ >
16681560 ) ;
16691561 }
0 commit comments