From 8b39cea5f34a9e2ff98cfa7ab9c148778fc0bfcc Mon Sep 17 00:00:00 2001 From: npeter83 Date: Tue, 16 Jun 2026 01:46:32 +0200 Subject: [PATCH] fix(nav): portal account popover to body (stacking + click-through) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The nav's .glass backdrop-filter makes it a containing block for fixed descendants and a stacking context, so the account popover's fixed inset-0 backdrop only covered the nav (not the viewport) and the popover sat below the main content — controls behind it stayed clickable. Portal the popover + its dismiss backdrop to with fixed coords computed from the trigger rect, so it's truly top-most (z-50) and blocks clicks underneath. --- frontend/src/components/NavSidebar.tsx | 38 ++++++++++++++++++++------ 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/frontend/src/components/NavSidebar.tsx b/frontend/src/components/NavSidebar.tsx index 992a2a0..3bffe2a 100644 --- a/frontend/src/components/NavSidebar.tsx +++ b/frontend/src/components/NavSidebar.tsx @@ -1,4 +1,5 @@ -import { useState } from "react"; +import { useRef, useState } from "react"; +import { createPortal } from "react-dom"; import { useTranslation } from "react-i18next"; import { BarChart3, @@ -35,6 +36,19 @@ export default function NavSidebar({ () => localStorage.getItem("siftlode.navCollapsed") === "1" ); const [acctOpen, setAcctOpen] = useState(false); + const acctBtnRef = useRef(null); + // Popover position (fixed, viewport coords). It's portaled to so it escapes the + // nav's backdrop-filter, which would otherwise trap fixed positioning + stacking and let + // clicks fall through to the controls behind it. + const [acctPos, setAcctPos] = useState<{ left: number; bottom: number }>({ left: 0, bottom: 0 }); + + function toggleAccount() { + if (!acctOpen) { + const r = acctBtnRef.current?.getBoundingClientRect(); + if (r) setAcctPos({ left: r.right + 8, bottom: window.innerHeight - r.bottom }); + } + setAcctOpen((o) => !o); + } function toggleCollapsed() { setCollapsed((c) => { @@ -128,7 +142,8 @@ export default function NavSidebar({
- {acctOpen && ( - <> -
setAcctOpen(false)} /> -
+ {acctOpen && + createPortal( + <> +
setAcctOpen(false)} /> +
-
- - )} +
+ , + document.body + )}