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 + )}