fix: mobil menü drawer'ı body'ye portal et — header transform'u fixed konumu bozuyordu
Header scroll efekti #floating-header-wrap'e transform uyguladığı için içindeki position:fixed overlay viewport yerine header'a göre konumlanıyordu. Drawer + overlay artık createPortal ile document.body'ye render ediliyor: sağ drawer, beyaz panel, tam ekran koyu overlay (z-100).
This commit is contained in:
+30
-21
@@ -1,6 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
import Link from "next/link";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { Menu, X, ChevronDown, Phone, ArrowRight } from "lucide-react";
|
||||
@@ -8,7 +9,6 @@ import { Menu, X, ChevronDown, Phone, ArrowRight } from "lucide-react";
|
||||
type NavService = { slug: string; title: string };
|
||||
|
||||
const LINKS = [
|
||||
{ href: "/", label: "Anasayfa" },
|
||||
{ href: "/cozumler", label: "Çözümler" },
|
||||
{ href: "/projeler", label: "Projeler" },
|
||||
{ href: "/blog", label: "Blog" },
|
||||
@@ -25,10 +25,13 @@ export function MobileMenu({
|
||||
phone: string;
|
||||
phoneRaw: string;
|
||||
}) {
|
||||
const [mounted, setMounted] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
const [servicesOpen, setServicesOpen] = useState(false);
|
||||
const pathname = usePathname();
|
||||
|
||||
useEffect(() => setMounted(true), []);
|
||||
|
||||
// Rota değişince menüyü kapat
|
||||
useEffect(() => {
|
||||
setOpen(false);
|
||||
@@ -42,36 +45,27 @@ export function MobileMenu({
|
||||
};
|
||||
}, [open]);
|
||||
|
||||
return (
|
||||
<div className="lg:hidden">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setOpen(true)}
|
||||
aria-label="Menüyü aç"
|
||||
aria-expanded={open}
|
||||
className="inline-flex size-9 items-center justify-center rounded-lg text-gray-700 transition-colors hover:bg-gray-100 hover:text-[var(--navy)]"
|
||||
>
|
||||
<Menu className="size-5" />
|
||||
</button>
|
||||
|
||||
{/* Overlay + drawer */}
|
||||
// Drawer + overlay — header transform bağlamından kaçmak için body'ye portal
|
||||
const overlay = (
|
||||
<div
|
||||
className={`fixed inset-0 z-[60] lg:hidden ${
|
||||
className={`fixed inset-0 z-[100] lg:hidden ${
|
||||
open ? "" : "pointer-events-none"
|
||||
}`}
|
||||
aria-hidden={!open}
|
||||
>
|
||||
{/* Backdrop */}
|
||||
{/* Koyu overlay */}
|
||||
<div
|
||||
onClick={() => setOpen(false)}
|
||||
className={`absolute inset-0 bg-black/40 backdrop-blur-sm transition-opacity duration-300 ${
|
||||
className={`absolute inset-0 bg-black/50 transition-opacity duration-300 ${
|
||||
open ? "opacity-100" : "opacity-0"
|
||||
}`}
|
||||
/>
|
||||
|
||||
{/* Panel */}
|
||||
{/* Sağ drawer — beyaz panel */}
|
||||
<div
|
||||
className={`absolute right-0 top-0 flex h-full w-[86%] max-w-sm flex-col bg-white shadow-2xl transition-transform duration-300 ease-out ${
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
className={`absolute right-0 top-0 flex h-full w-[82%] max-w-[340px] flex-col bg-white shadow-2xl transition-transform duration-300 ease-out ${
|
||||
open ? "translate-x-0" : "translate-x-full"
|
||||
}`}
|
||||
>
|
||||
@@ -84,7 +78,7 @@ export function MobileMenu({
|
||||
type="button"
|
||||
onClick={() => setOpen(false)}
|
||||
aria-label="Menüyü kapat"
|
||||
className="inline-flex size-9 items-center justify-center rounded-lg text-gray-600 transition-colors hover:bg-gray-100 hover:text-[var(--navy)]"
|
||||
className="-mr-2 inline-flex size-9 items-center justify-center rounded-lg text-gray-600 transition-colors hover:bg-gray-100 hover:text-[var(--navy)]"
|
||||
>
|
||||
<X className="size-5" />
|
||||
</button>
|
||||
@@ -133,7 +127,7 @@ export function MobileMenu({
|
||||
</div>
|
||||
)}
|
||||
|
||||
{LINKS.filter((l) => l.href !== "/").map((l) => (
|
||||
{LINKS.map((l) => (
|
||||
<Link
|
||||
key={l.href}
|
||||
href={l.href}
|
||||
@@ -163,6 +157,21 @@ export function MobileMenu({
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="lg:hidden">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setOpen(true)}
|
||||
aria-label="Menüyü aç"
|
||||
aria-expanded={open}
|
||||
className="inline-flex size-9 items-center justify-center rounded-lg text-gray-700 transition-colors hover:bg-gray-100 hover:text-[var(--navy)]"
|
||||
>
|
||||
<Menu className="size-5" />
|
||||
</button>
|
||||
|
||||
{mounted && createPortal(overlay, document.body)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user