| import { useEffect } from "react"; |
| import { NavLink } from "react-router-dom"; |
| import { X } from "lucide-react"; |
| import { NAV_ITEMS } from "./Sidebar.jsx"; |
| import "./MobileMenu.css"; |
|
|
| export default function MobileMenu({ open, onClose }) { |
| useEffect(() => { |
| if (!open) return undefined; |
|
|
| const previousOverflow = document.body.style.overflow; |
| document.body.style.overflow = "hidden"; |
|
|
| const onKeyDown = (event) => { |
| if (event.key === "Escape") onClose(); |
| }; |
| window.addEventListener("keydown", onKeyDown); |
|
|
| return () => { |
| document.body.style.overflow = previousOverflow; |
| window.removeEventListener("keydown", onKeyDown); |
| }; |
| }, [open, onClose]); |
|
|
| if (!open) return null; |
|
|
| return ( |
| <div className="mobile-menu" role="dialog" aria-modal="true" aria-label="Visualization menu"> |
| <button |
| className="mobile-menu__backdrop" |
| onClick={onClose} |
| aria-label="Close visualization menu" |
| /> |
| |
| <section className="mobile-menu__panel"> |
| <header className="mobile-menu__header"> |
| <div> |
| <p className="label">Navigation</p> |
| <h2 className="mobile-menu__title">Visualizations</h2> |
| </div> |
| <button className="ghost mobile-menu__close" onClick={onClose} aria-label="Close menu"> |
| <X size={18} /> |
| </button> |
| </header> |
| |
| <nav className="mobile-menu__nav" aria-label="Visualization links"> |
| {NAV_ITEMS.map(({ to, label, Icon }) => ( |
| <NavLink |
| key={to} |
| to={to} |
| className={({ isActive }) => |
| `mobile-menu__link ${isActive ? "mobile-menu__link--active" : ""}` |
| } |
| onClick={onClose} |
| > |
| <Icon size={18} strokeWidth={1.6} /> |
| <span>{label}</span> |
| </NavLink> |
| ))} |
| </nav> |
| </section> |
| </div> |
| ); |
| } |
|
|