From 4f1144cc7ffbc50b49a3455aaac92598ed44d944 Mon Sep 17 00:00:00 2001 From: ciregenz Date: Sun, 19 Jul 2026 17:35:54 -0700 Subject: [PATCH] [eric] shell: peeked sidebar no longer collapses mid-reach (grace-delayed close, cancel on re-enter) --- .../src/app/components/Layout/AppShell.tsx | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/frontend/src/app/components/Layout/AppShell.tsx b/frontend/src/app/components/Layout/AppShell.tsx index 95eb2a26..1351d93f 100644 --- a/frontend/src/app/components/Layout/AppShell.tsx +++ b/frontend/src/app/components/Layout/AppShell.tsx @@ -445,12 +445,16 @@ const AppShell: React.FC = () => { const sidebarAway = (sidebarCollapsed || fsActive) && isDashboardViewActive; const [sidePeek, setSidePeek] = useState(false); useEffect(() => { if (!sidebarAway) setSidePeek(false); }, [sidebarAway]); - useEffect(() => { - if (!sidePeek) return undefined; - const onMove = (e: MouseEvent): void => { if (e.clientX > sidebarWidth + 60) setSidePeek(false); }; - window.addEventListener('mousemove', onMove); - return () => window.removeEventListener('mousemove', onMove); - }, [sidePeek, sidebarWidth]); + // Close-on-leave with a grace delay (cancelled on re-enter): a bare mouseLeave closed the peek the + // instant the cursor dipped past the panel edge while reaching for an item, so clicks never landed. + const peekCloseTimerRef = useRef | null>(null); + const cancelPeekClose = useCallback(() => { + if (peekCloseTimerRef.current) { clearTimeout(peekCloseTimerRef.current); peekCloseTimerRef.current = null; } + }, []); + const schedulePeekClose = useCallback(() => { + cancelPeekClose(); + peekCloseTimerRef.current = setTimeout(() => setSidePeek(false), 260); + }, [cancelPeekClose]); // Fullscreen still hides the top-center island anchor + banners; the sidebar floats in on peek. const fsHideChrome = fsActive; // In overlay mode the panel stays MOUNTED (so it can slide out, not vanish); sidePeek only drives the slide. @@ -601,7 +605,7 @@ const AppShell: React.FC = () => { return ( {sidebarAway && !sidePeek && ( - setSidePeek(true)} sx={{ position: 'fixed', top: 0, left: 0, bottom: 0, width: 14, zIndex: 2147483000, pointerEvents: 'auto' }} /> + { cancelPeekClose(); setSidePeek(true); }} sx={{ position: 'fixed', top: 0, left: 0, bottom: 0, width: 14, zIndex: 2147483000, pointerEvents: 'auto' }} /> )} {/* Top bar dropped (Arc/Zen): a zero-height anchor left only to float the agent-activity island at top-center; the island renders nothing when idle. */} { {((!sidebarCollapsed && !fsHideChrome) || sideOverlay) && ( <> { if (sideOverlay) setSidePeek(false); }} + onMouseEnter={() => { if (sideOverlay) cancelPeekClose(); }} + onMouseLeave={() => { if (sideOverlay) schedulePeekClose(); }} onWheel={handleSidebarSwipe} sx={{ width: sidebarWidth,