Files
gov-portals-monorepo/DBIS/components/layout/NavDropdown.tsx
2026-02-13 10:30:56 -08:00

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>
);
}