Feat: Add notifications menu

This commit is contained in:
MangoPig
2026-06-16 17:00:51 +01:00
parent fd429bdcdd
commit 248a0b1828
8 changed files with 543 additions and 1 deletions
@@ -0,0 +1,56 @@
import { createEffect, createSignal, createUniqueId, onCleanup, type JSX } from "solid-js";
import { NotificationsButton } from "./NotificationsButton";
import { NotificationsMenu } from "./NotificationsMenu";
import styles from "./NotificationsNav.module.scss";
export const NotificationsNav = (): JSX.Element => {
const [isOpen, setIsOpen] = createSignal(false);
const menuId = createUniqueId();
let rootRef: HTMLDivElement | undefined;
let menuRef: HTMLDivElement | undefined;
const closeMenu = (): void => {
setIsOpen(false);
};
const toggleMenu = (): void => {
setIsOpen((open) => !open);
};
createEffect(() => {
if (!isOpen()) return;
const handlePointerDown = (event: PointerEvent): void => {
if (!rootRef) return;
const target = event.target;
if (target instanceof Node && !rootRef.contains(target)) {
closeMenu();
}
};
const handleKeyDown = (event: KeyboardEvent): void => {
if (event.key === "Escape") {
closeMenu();
}
};
document.addEventListener("pointerdown", handlePointerDown);
document.addEventListener("keydown", handleKeyDown);
menuRef?.querySelector<HTMLButtonElement>("[role='menuitem']")?.focus();
onCleanup(() => {
document.removeEventListener("pointerdown", handlePointerDown);
document.removeEventListener("keydown", handleKeyDown);
});
});
return (
<div class={styles.root} ref={rootRef}>
<NotificationsButton isOpen={isOpen()} menuId={menuId} onToggle={toggleMenu} />
{isOpen() ? (
<NotificationsMenu id={menuId} menuRef={(element) => (menuRef = element)} onSelect={closeMenu} />
) : null}
</div>
);
};