fix(nav): remove backdrop div so the account popover frosts

The full-screen transparent dismiss backdrop sat directly behind the popover and acted as
a compositing layer, so the popover's backdrop-filter sampled it (empty) instead of the
page — making the glass look fully solid. Drop the backdrop and dismiss via document
mousedown/Escape listeners (like the other menus). Now backdrop-filter samples real
content and the frost shows.
This commit is contained in:
npeter83 2026-06-16 01:54:01 +02:00
parent 0c12f44d81
commit 416ffa3fb8

View file

@ -1,4 +1,4 @@
import { useRef, useState } from "react";
import { useEffect, useRef, useState } from "react";
import { createPortal } from "react-dom";
import { useTranslation } from "react-i18next";
import {
@ -37,6 +37,7 @@ export default function NavSidebar({
);
const [acctOpen, setAcctOpen] = useState(false);
const acctBtnRef = useRef<HTMLButtonElement | null>(null);
const acctPanelRef = useRef<HTMLDivElement | 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.
@ -50,6 +51,27 @@ export default function NavSidebar({
setAcctOpen((o) => !o);
}
// Dismiss on outside click / Escape via document listeners — NOT a full-screen backdrop
// div, which (sitting between the popover and the page) would break the popover's
// backdrop-filter and make it look solid.
useEffect(() => {
if (!acctOpen) return;
function onDoc(e: MouseEvent) {
const t = e.target as Node;
if (acctPanelRef.current?.contains(t) || acctBtnRef.current?.contains(t)) return;
setAcctOpen(false);
}
function onKey(e: KeyboardEvent) {
if (e.key === "Escape") setAcctOpen(false);
}
document.addEventListener("mousedown", onDoc);
document.addEventListener("keydown", onKey);
return () => {
document.removeEventListener("mousedown", onDoc);
document.removeEventListener("keydown", onKey);
};
}, [acctOpen]);
function toggleCollapsed() {
setCollapsed((c) => {
const next = !c;
@ -157,12 +179,11 @@ export default function NavSidebar({
{acctOpen &&
createPortal(
<>
<div className="fixed inset-0 z-40" onClick={() => setAcctOpen(false)} />
<div
style={{ position: "fixed", left: acctPos.left, bottom: acctPos.bottom }}
className="glass w-60 rounded-xl p-3 z-50 animate-[popIn_0.16s_ease]"
>
<div
ref={acctPanelRef}
style={{ position: "fixed", left: acctPos.left, bottom: acctPos.bottom }}
className="glass 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">
<AvatarImg
src={me.avatar_url}
@ -199,8 +220,7 @@ export default function NavSidebar({
{t("header.account.signOut")}
</button>
</div>
</div>
</>,
</div>,
document.body
)}
</div>