fix(base): close toolbar popovers on escape via document keydown

This commit is contained in:
Philipinho
2026-04-18 20:31:54 +01:00
parent 83d55d9bd3
commit 5de9a69130
@@ -52,28 +52,35 @@ export function BaseToolbar({
const [exporting, setExporting] = useState(false); const [exporting, setExporting] = useState(false);
const toolbarRightRef = useRef<HTMLDivElement>(null); const toolbarRightRef = useRef<HTMLDivElement>(null);
// Mantine `<Popover>`'s built-in `closeOnClickOutside` does not fire // Mantine `<Popover>`'s built-in dismiss handlers don't fire reliably
// reliably for the toolbar popovers (same issue that drove the property // for the toolbar popovers (same issue that drove the property menu to
// menu to use a custom listener in `grid-container.tsx`). Close any open // use custom listeners in `grid-container.tsx`). Close any open toolbar
// toolbar popover when a mousedown lands outside the toolbar cluster // popover on outside mousedown AND on ESC.
// AND outside any open Mantine dropdown (marked `role="dialog"`).
useEffect(() => { useEffect(() => {
if (!sortOpened && !filterOpened && !fieldsOpened) return; if (!sortOpened && !filterOpened && !fieldsOpened) return;
const handler = (e: MouseEvent) => { const closeAll = () => {
const target = e.target as HTMLElement | null;
if (!target) return;
if (toolbarRightRef.current?.contains(target)) return;
if (target.closest('[role="dialog"]')) return;
setSortOpened(false); setSortOpened(false);
setFilterOpened(false); setFilterOpened(false);
setFieldsOpened(false); setFieldsOpened(false);
}; };
const mouseHandler = (e: MouseEvent) => {
const target = e.target as HTMLElement | null;
if (!target) return;
if (toolbarRightRef.current?.contains(target)) return;
if (target.closest('[role="dialog"]')) return;
closeAll();
};
const keyHandler = (e: KeyboardEvent) => {
if (e.key === "Escape") closeAll();
};
const id = setTimeout(() => { const id = setTimeout(() => {
document.addEventListener("mousedown", handler); document.addEventListener("mousedown", mouseHandler);
}, 0); }, 0);
document.addEventListener("keydown", keyHandler);
return () => { return () => {
clearTimeout(id); clearTimeout(id);
document.removeEventListener("mousedown", handler); document.removeEventListener("mousedown", mouseHandler);
document.removeEventListener("keydown", keyHandler);
}; };
}, [sortOpened, filterOpened, fieldsOpened]); }, [sortOpened, filterOpened, fieldsOpened]);