58 lines
2.2 KiB
TypeScript
58 lines
2.2 KiB
TypeScript
|
|
"use client";
|
||
|
|
|
||
|
|
import Link from "next/link";
|
||
|
|
import { useState, useRef, useEffect } from "react";
|
||
|
|
import type { NavItem } from "@public-web-portals/shared";
|
||
|
|
|
||
|
|
export function NavDropdown({ item }: { item: NavItem }) {
|
||
|
|
const [open, setOpen] = useState(false);
|
||
|
|
const ref = useRef<HTMLDivElement>(null);
|
||
|
|
|
||
|
|
useEffect(() => {
|
||
|
|
function handleClickOutside(event: MouseEvent) {
|
||
|
|
if (ref.current && !ref.current.contains(event.target as Node)) setOpen(false);
|
||
|
|
}
|
||
|
|
document.addEventListener("mousedown", handleClickOutside);
|
||
|
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
||
|
|
}, []);
|
||
|
|
|
||
|
|
return (
|
||
|
|
<div className="relative" ref={ref}>
|
||
|
|
<button
|
||
|
|
type="button"
|
||
|
|
className="flex items-center gap-1 rounded px-3 py-2 text-sm font-medium text-neutral-700 hover:bg-neutral-100 hover:text-neutral-900 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-inset"
|
||
|
|
aria-expanded={open}
|
||
|
|
aria-haspopup="true"
|
||
|
|
aria-controls={`nav-menu-${item.label.replace(/\s/g, "-")}`}
|
||
|
|
id={`nav-button-${item.label.replace(/\s/g, "-")}`}
|
||
|
|
onClick={() => setOpen(!open)}
|
||
|
|
>
|
||
|
|
{item.label}
|
||
|
|
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden>
|
||
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
|
||
|
|
</svg>
|
||
|
|
</button>
|
||
|
|
<ul
|
||
|
|
id={`nav-menu-${item.label.replace(/\s/g, "-")}`}
|
||
|
|
role="menu"
|
||
|
|
aria-orientation="vertical"
|
||
|
|
aria-labelledby={`nav-button-${item.label.replace(/\s/g, "-")}`}
|
||
|
|
className={`absolute left-0 top-full z-10 mt-1 min-w-[12rem] rounded-md border border-neutral-200 bg-white py-1 shadow-lg ${open ? "block" : "hidden"}`}
|
||
|
|
>
|
||
|
|
{item.children?.map((child) => (
|
||
|
|
<li key={child.href} role="none">
|
||
|
|
<Link
|
||
|
|
href={child.href}
|
||
|
|
role="menuitem"
|
||
|
|
className="block px-4 py-2 text-sm text-neutral-700 hover:bg-neutral-100 focus:bg-neutral-100 focus:outline-none"
|
||
|
|
onClick={() => setOpen(false)}
|
||
|
|
>
|
||
|
|
{child.label}
|
||
|
|
</Link>
|
||
|
|
</li>
|
||
|
|
))}
|
||
|
|
</ul>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|