From c0641a2c1d23af95369cb9a9ec1e069ce3099085 Mon Sep 17 00:00:00 2001 From: Michael Suchacz <203725896+ibetitsmike@users.noreply.github.com> Date: Tue, 25 Nov 2025 15:21:16 +0000 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=A4=96=20fix:=20use=20portal=20for=20?= =?UTF-8?q?UntrackedStatus=20popup=20to=20escape=20overflow:hidden?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The popup was being clipped by parent containers with overflow:hidden. Now uses createPortal with fixed positioning and dynamic coordinates calculated from the trigger element's bounding rect. --- .../CodeReview/UntrackedStatus.tsx | 102 ++++++++++++------ 1 file changed, 71 insertions(+), 31 deletions(-) diff --git a/src/browser/components/RightSidebar/CodeReview/UntrackedStatus.tsx b/src/browser/components/RightSidebar/CodeReview/UntrackedStatus.tsx index 9ddae6998e..51bac94fc9 100644 --- a/src/browser/components/RightSidebar/CodeReview/UntrackedStatus.tsx +++ b/src/browser/components/RightSidebar/CodeReview/UntrackedStatus.tsx @@ -2,7 +2,8 @@ * UntrackedStatus - Shows untracked files count with interactive tooltip */ -import React, { useState, useEffect, useRef } from "react"; +import React, { useState, useEffect, useRef, useLayoutEffect } from "react"; +import { createPortal } from "react-dom"; import { cn } from "@/common/lib/utils"; interface UntrackedStatusProps { @@ -22,10 +23,40 @@ export const UntrackedStatus: React.FC = ({ const [isLoading, setIsLoading] = useState(false); const [showTooltip, setShowTooltip] = useState(false); const [isTracking, setIsTracking] = useState(false); + const [popupPosition, setPopupPosition] = useState<{ top: number; right: number } | null>(null); const containerRef = useRef(null); + const popupRef = useRef(null); const hasLoadedOnce = useRef(false); const loadingRef = useRef(false); // Prevent concurrent loads + // Calculate popup position when shown + useLayoutEffect(() => { + if (!showTooltip || !containerRef.current) { + setPopupPosition(null); + return; + } + + const updatePosition = () => { + const container = containerRef.current; + if (!container) return; + + const rect = container.getBoundingClientRect(); + setPopupPosition({ + top: rect.bottom + 8, // 8px gap below anchor + right: window.innerWidth - rect.right, + }); + }; + + updatePosition(); + + window.addEventListener("resize", updatePosition); + window.addEventListener("scroll", updatePosition, true); + return () => { + window.removeEventListener("resize", updatePosition); + window.removeEventListener("scroll", updatePosition, true); + }; + }, [showTooltip]); + // Load untracked files useEffect(() => { let cancelled = false; @@ -78,7 +109,10 @@ export const UntrackedStatus: React.FC = ({ if (!showTooltip) return; const handleClickOutside = (e: MouseEvent) => { - if (containerRef.current && !containerRef.current.contains(e.target as Node)) { + const target = e.target as Node; + const clickedContainer = containerRef.current?.contains(target); + const clickedPopup = popupRef.current?.contains(target); + if (!clickedContainer && !clickedPopup) { setShowTooltip(false); } }; @@ -121,7 +155,7 @@ export const UntrackedStatus: React.FC = ({ const hasUntracked = count > 0; return ( -
+
= ({ {isLoading ? "..." : `${count} Untracked`}
- {showTooltip && hasUntracked && ( -
-
- Untracked Files ({count}) -
-
- {untrackedFiles.map((file) => ( -
- {file} -
- ))} -
- -
- )} +
+ Untracked Files ({count}) +
+
+ {untrackedFiles.map((file) => ( +
+ {file} +
+ ))} +
+ +
, + document.body + )}
); }; From a0859e945c3220b0305cacdf9000989042138436 Mon Sep 17 00:00:00 2001 From: Michael Suchacz <203725896+ibetitsmike@users.noreply.github.com> Date: Tue, 25 Nov 2025 15:23:50 +0000 Subject: [PATCH 2/2] fmt --- .../components/RightSidebar/CodeReview/UntrackedStatus.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/browser/components/RightSidebar/CodeReview/UntrackedStatus.tsx b/src/browser/components/RightSidebar/CodeReview/UntrackedStatus.tsx index 51bac94fc9..c6c5169703 100644 --- a/src/browser/components/RightSidebar/CodeReview/UntrackedStatus.tsx +++ b/src/browser/components/RightSidebar/CodeReview/UntrackedStatus.tsx @@ -168,7 +168,9 @@ export const UntrackedStatus: React.FC = ({ {isLoading ? "..." : `${count} Untracked`} - {showTooltip && hasUntracked && popupPosition && + {showTooltip && + hasUntracked && + popupPosition && createPortal(