2026-05-12 19:59:27 +07:00
|
|
|
"use client";
|
|
|
|
|
import Image from "next/image";
|
2026-06-15 16:32:48 +07:00
|
|
|
import Logo from "@/image/Logo.svg";
|
2026-06-22 16:22:37 +07:00
|
|
|
import { ListIcon, XIcon } from "@phosphor-icons/react/dist/ssr";
|
2026-05-12 19:59:27 +07:00
|
|
|
import Link from "next/link";
|
2026-06-22 16:22:37 +07:00
|
|
|
import { useState, useEffect } from "react";
|
2026-09-04 14:58:16 +07:00
|
|
|
import { usePathname } from "next/navigation";
|
2026-05-12 19:59:27 +07:00
|
|
|
|
|
|
|
|
export default function Navbar() {
|
2026-06-22 16:22:37 +07:00
|
|
|
const [open, setOpen] = useState(false);
|
2026-09-24 10:25:27 +07:00
|
|
|
const [activeSection, setActiveSection] = useState("");
|
2026-09-04 14:58:16 +07:00
|
|
|
const pathname = usePathname();
|
|
|
|
|
const isContact = pathname === "/contact";
|
|
|
|
|
const active = isContact ? "contact" : activeSection;
|
2026-05-12 19:59:27 +07:00
|
|
|
|
|
|
|
|
const menu = [
|
2026-09-04 14:58:16 +07:00
|
|
|
{ label: "About Us", url: "/#about-us", id: "about-us" },
|
|
|
|
|
{ label: "Services", url: "/#services", id: "services" },
|
|
|
|
|
{ label: "Portfolio", url: "/#portfolio", id: "portfolio" },
|
|
|
|
|
{ label: "Process", url: "/#process", id: "process" },
|
|
|
|
|
{ label: "Contact", url: "/contact", id: "contact" },
|
2026-05-12 19:59:27 +07:00
|
|
|
];
|
|
|
|
|
|
2026-06-22 16:22:37 +07:00
|
|
|
useEffect(() => {
|
2026-09-04 14:58:16 +07:00
|
|
|
if (isContact) return;
|
|
|
|
|
const ids = ["about-us", "services", "portfolio", "process"];
|
2026-06-22 16:22:37 +07:00
|
|
|
const sections = ids.map((id) => document.getElementById(id)).filter(Boolean) as HTMLElement[];
|
|
|
|
|
const observer = new IntersectionObserver(
|
|
|
|
|
(entries) => {
|
|
|
|
|
entries.forEach((entry) => {
|
2026-09-04 14:58:16 +07:00
|
|
|
if (entry.isIntersecting) setActiveSection(entry.target.id);
|
2026-06-22 16:22:37 +07:00
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
{ rootMargin: "-50% 0px -50% 0px" }
|
|
|
|
|
);
|
|
|
|
|
sections.forEach((section) => observer.observe(section));
|
|
|
|
|
return () => observer.disconnect();
|
2026-09-04 14:58:16 +07:00
|
|
|
}, [isContact]);
|
2026-06-22 16:22:37 +07:00
|
|
|
|
2026-05-12 19:59:27 +07:00
|
|
|
return (
|
2026-06-22 16:22:37 +07:00
|
|
|
<>
|
|
|
|
|
<div className="bg-white px-4 h-19.5 md:h-18.5 flex items-center w-full justify-between md:py-5.5 md:px-16 sticky top-0 left-0 right-0 z-50">
|
|
|
|
|
<Image src={Logo} width={118} className="w-fit h-7.5" alt="logo" />
|
|
|
|
|
<button onClick={() => setOpen(true)} className="md:hidden">
|
|
|
|
|
<ListIcon className="size-8 text-secondary-400 cursor-pointer" />
|
|
|
|
|
</button>
|
|
|
|
|
<div className="md:flex gap-7.5 hidden">
|
|
|
|
|
{menu?.map((item) => (
|
|
|
|
|
<Link href={item.url} key={item.label}>
|
|
|
|
|
<div className={`font-medium ${active === item.id ? "text-primary-800" : "text-title"}`}>{item.label}</div>
|
|
|
|
|
</Link>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{open && <div className="fixed inset-0 bg-black/50 z-50 md:hidden" onClick={() => setOpen(false)} />}
|
|
|
|
|
|
|
|
|
|
<div className={`fixed top-0 right-0 h-full w-64 bg-white z-50 transform transition-transform duration-300 md:hidden ${open ? "translate-x-0" : "translate-x-full"}`}>
|
|
|
|
|
<div className="flex justify-between items-center p-4">
|
|
|
|
|
<Image src={Logo} width={118} className="w-fit h-7.5" alt="logo" />
|
|
|
|
|
<button onClick={() => setOpen(false)}>
|
|
|
|
|
<XIcon className="size-6 text-secondary-400" />
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="flex flex-col gap-4 p-4">
|
|
|
|
|
{menu?.map((item) => (
|
|
|
|
|
<Link href={item.url} key={item.label} onClick={() => setOpen(false)}>
|
|
|
|
|
<div className={`font-medium ${active === item.id ? "text-primary-800" : "text-title"}`}>{item.label}</div>
|
|
|
|
|
</Link>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
2026-05-12 19:59:27 +07:00
|
|
|
</div>
|
2026-06-22 16:22:37 +07:00
|
|
|
</>
|
2026-05-12 19:59:27 +07:00
|
|
|
);
|
|
|
|
|
}
|