fix(nav): portal account popover to body (stacking + click-through)
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 <body> with fixed coords computed from the trigger rect, so it's truly top-most (z-50) and blocks clicks underneath.
This commit is contained in:
parent
2442e462c4
commit
8b39cea5f3
1 changed files with 29 additions and 9 deletions
|
|
@ -1,4 +1,5 @@
|
||||||
import { useState } from "react";
|
import { useRef, useState } from "react";
|
||||||
|
import { createPortal } from "react-dom";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import {
|
import {
|
||||||
BarChart3,
|
BarChart3,
|
||||||
|
|
@ -35,6 +36,19 @@ export default function NavSidebar({
|
||||||
() => localStorage.getItem("siftlode.navCollapsed") === "1"
|
() => localStorage.getItem("siftlode.navCollapsed") === "1"
|
||||||
);
|
);
|
||||||
const [acctOpen, setAcctOpen] = useState(false);
|
const [acctOpen, setAcctOpen] = useState(false);
|
||||||
|
const acctBtnRef = useRef<HTMLButtonElement | null>(null);
|
||||||
|
// Popover position (fixed, viewport coords). It's portaled to <body> 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() {
|
function toggleCollapsed() {
|
||||||
setCollapsed((c) => {
|
setCollapsed((c) => {
|
||||||
|
|
@ -128,7 +142,8 @@ export default function NavSidebar({
|
||||||
|
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<button
|
<button
|
||||||
onClick={() => setAcctOpen((o) => !o)}
|
ref={acctBtnRef}
|
||||||
|
onClick={toggleAccount}
|
||||||
title={collapsed ? name : undefined}
|
title={collapsed ? name : undefined}
|
||||||
className={`${rowBase} ${collapsed ? "justify-center px-0" : ""} text-muted hover:text-fg hover:bg-card`}
|
className={`${rowBase} ${collapsed ? "justify-center px-0" : ""} text-muted hover:text-fg hover:bg-card`}
|
||||||
>
|
>
|
||||||
|
|
@ -140,10 +155,14 @@ export default function NavSidebar({
|
||||||
{!collapsed && <span className="truncate flex-1 text-left">{name}</span>}
|
{!collapsed && <span className="truncate flex-1 text-left">{name}</span>}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{acctOpen && (
|
{acctOpen &&
|
||||||
|
createPortal(
|
||||||
<>
|
<>
|
||||||
<div className="fixed inset-0 z-20" onClick={() => setAcctOpen(false)} />
|
<div className="fixed inset-0 z-40" onClick={() => setAcctOpen(false)} />
|
||||||
<div className="glass-menu absolute left-full bottom-0 ml-2 w-60 rounded-xl p-3 z-30 animate-[popIn_0.16s_ease]">
|
<div
|
||||||
|
style={{ position: "fixed", left: acctPos.left, bottom: acctPos.bottom }}
|
||||||
|
className="glass-menu w-60 rounded-xl p-3 z-50 animate-[popIn_0.16s_ease]"
|
||||||
|
>
|
||||||
<div className="flex items-center gap-3 pb-3 border-b border-border">
|
<div className="flex items-center gap-3 pb-3 border-b border-border">
|
||||||
<AvatarImg
|
<AvatarImg
|
||||||
src={me.avatar_url}
|
src={me.avatar_url}
|
||||||
|
|
@ -181,7 +200,8 @@ export default function NavSidebar({
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>,
|
||||||
|
document.body
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue