From 8d2e7808d098334395cf58501db4653381f7567a Mon Sep 17 00:00:00 2001 From: 777genius Date: Mon, 18 May 2026 02:11:48 +0300 Subject: [PATCH] fix(team): prevent runtime tooltip over controls --- .../components/team/members/MemberCard.tsx | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/src/renderer/components/team/members/MemberCard.tsx b/src/renderer/components/team/members/MemberCard.tsx index a371a4c7..3ab7a1f2 100644 --- a/src/renderer/components/team/members/MemberCard.tsx +++ b/src/renderer/components/team/members/MemberCard.tsx @@ -122,6 +122,17 @@ function notifyRuntimeTelemetryTooltipOpen(id: string): void { ); } +function isRuntimeTelemetryTooltipBlockedTarget( + currentTarget: EventTarget, + target: EventTarget | null +): boolean { + if (!(currentTarget instanceof Element) || !(target instanceof Element)) { + return false; + } + const blockedTarget = target.closest('button,a,[title],[data-runtime-telemetry-exempt="true"]'); + return Boolean(blockedTarget && blockedTarget !== currentTarget); +} + function splitRuntimeSummaryMemory(runtimeSummary: string | undefined): { summary: string | undefined; memory: string | undefined; @@ -716,6 +727,7 @@ export const MemberCard = memo(function MemberCard({ runtimeTelemetryTooltipIdRef.current = createRuntimeTelemetryTooltipId(); } const runtimeTelemetryTooltipId = runtimeTelemetryTooltipIdRef.current; + const runtimeTelemetryPointerBlockedRef = useRef(false); const runtimeTelemetryTooltipTimerRef = useRef | null>(null); const [runtimeTelemetryTooltipOpen, setRuntimeTelemetryTooltipOpen] = useState(false); const clearRuntimeTelemetryTooltipTimer = useCallback(() => { @@ -736,7 +748,7 @@ export const MemberCard = memo(function MemberCard({ closeRuntimeTelemetryTooltip(); return; } - if (runtimeTelemetryTooltipOpen) { + if (runtimeTelemetryPointerBlockedRef.current || runtimeTelemetryTooltipOpen) { return; } runtimeTelemetryTooltipTimerRef.current = setTimeout(() => { @@ -787,10 +799,24 @@ export const MemberCard = memo(function MemberCard({ }; }, [closeRuntimeTelemetryTooltip, runtimeTelemetryTooltipId, showRuntimeTelemetryTooltip]); const handleRuntimeTelemetryPointerLeave = useCallback(() => { + runtimeTelemetryPointerBlockedRef.current = false; if (showRuntimeTelemetryTooltip) { closeRuntimeTelemetryTooltip(); } }, [closeRuntimeTelemetryTooltip, showRuntimeTelemetryTooltip]); + const handleRuntimeTelemetryPointerBlockCapture = useCallback( + (event: React.PointerEvent) => { + if (!showRuntimeTelemetryTooltip) { + return; + } + const blocked = isRuntimeTelemetryTooltipBlockedTarget(event.currentTarget, event.target); + runtimeTelemetryPointerBlockedRef.current = blocked; + if (blocked) { + closeRuntimeTelemetryTooltip(); + } + }, + [closeRuntimeTelemetryTooltip, showRuntimeTelemetryTooltip] + ); const showStartingSkeleton = !isRemoved && presenceLabel === 'starting' && @@ -956,6 +982,8 @@ export const MemberCard = memo(function MemberCard({ isRemoved && 'opacity-50', spawnCardClass )} + onPointerOverCapture={handleRuntimeTelemetryPointerBlockCapture} + onPointerMoveCapture={handleRuntimeTelemetryPointerBlockCapture} onPointerLeave={handleRuntimeTelemetryPointerLeave} >
- + worktree