الملفات
gracesalmoun/components/mobile-nav.tsx
2026-04-29 16:55:25 +03:00

106 أسطر
2.8 KiB
TypeScript

"use client";
import Link from "next/link";
import { useEffect, useState } from "react";
type NavItem = {
label: string;
href: string;
};
type MobileNavProps = {
items: NavItem[];
dir: "rtl" | "ltr";
openLabel: string;
closeLabel: string;
};
export function MobileNav({ items, dir, openLabel, closeLabel }: MobileNavProps) {
const [open, setOpen] = useState(false);
useEffect(() => {
if (!open) {
return;
}
const previousOverflow = document.body.style.overflow;
const media = window.matchMedia("(min-width: 768px)");
const handleHashChange = () => {
setOpen(false);
};
const handleKeyDown = (event: KeyboardEvent) => {
if (event.key === "Escape") {
setOpen(false);
}
};
const handleMediaChange = (event: MediaQueryListEvent) => {
if (event.matches) {
setOpen(false);
}
};
document.body.style.overflow = "hidden";
window.addEventListener("hashchange", handleHashChange);
document.addEventListener("keydown", handleKeyDown);
media.addEventListener("change", handleMediaChange);
return () => {
document.body.style.overflow = previousOverflow;
window.removeEventListener("hashchange", handleHashChange);
document.removeEventListener("keydown", handleKeyDown);
media.removeEventListener("change", handleMediaChange);
};
}, [open]);
const label = open ? closeLabel : openLabel;
return (
<div className="md:hidden">
<button
type="button"
className="theme-toggle mobile-menu-toggle"
aria-expanded={open}
aria-label={label}
title={label}
onClick={() => setOpen((current) => !current)}
>
<span className="sr-only">{label}</span>
{open ? (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" aria-hidden="true">
<path d="M6 6 18 18" />
<path d="M18 6 6 18" />
</svg>
) : (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" aria-hidden="true">
<path d="M4 7h16" />
<path d="M4 12h16" />
<path d="M4 17h16" />
</svg>
)}
</button>
{open ? (
<div className="mobile-menu-panel">
<nav aria-label="Mobile primary">
<ul className="mobile-menu-list">
{items.map((item) => (
<li key={item.href}>
<Link
href={item.href}
className={`mobile-menu-link ${dir === "rtl" ? "text-right" : ""}`}
onClick={() => setOpen(false)}
>
{item.label}
</Link>
</li>
))}
</ul>
</nav>
</div>
) : null}
</div>
);
}