113 lines
3.4 KiB
TypeScript
113 lines
3.4 KiB
TypeScript
|
|
"use client";
|
||
|
|
|
||
|
|
import Image from "next/image";
|
||
|
|
import { useEffect, useRef, useState } from "react";
|
||
|
|
import { gsap } from "gsap";
|
||
|
|
import Button from "./Button";
|
||
|
|
import SmoothScrollLink from "@/components/ui/smooth-scroll-link";
|
||
|
|
import Link from "next/link";
|
||
|
|
import { usePageTransition } from "@/layout/Layout";
|
||
|
|
|
||
|
|
const Navbar = () => {
|
||
|
|
const navbarRef = useRef<HTMLDivElement>(null);
|
||
|
|
const [scrolled, setScrolled] = useState(false);
|
||
|
|
const [showNavbar, setShowNavbar] = useState(true);
|
||
|
|
const { startTransition } = usePageTransition();
|
||
|
|
|
||
|
|
const [lastScrollY, setLastScrollY] = useState(0);
|
||
|
|
|
||
|
|
// ── GSAP: Initial slide-in ─────────────────────────────────────
|
||
|
|
useEffect(() => {
|
||
|
|
const el = navbarRef.current;
|
||
|
|
if (!el) return;
|
||
|
|
|
||
|
|
// Start off-screen
|
||
|
|
gsap.set(el, { yPercent: -100, opacity: 0 });
|
||
|
|
|
||
|
|
// Animate in
|
||
|
|
gsap.to(el, {
|
||
|
|
yPercent: 0,
|
||
|
|
opacity: 1,
|
||
|
|
duration: 1.2,
|
||
|
|
ease: "expo.out",
|
||
|
|
});
|
||
|
|
}, []);
|
||
|
|
|
||
|
|
// ── Scroll: Hide/show + background ─────────────────────────────
|
||
|
|
useEffect(() => {
|
||
|
|
const handleScroll = () => {
|
||
|
|
const currentScroll = window.scrollY;
|
||
|
|
|
||
|
|
// Hide on scroll down
|
||
|
|
if (currentScroll > lastScrollY && currentScroll > 100) {
|
||
|
|
setShowNavbar(false);
|
||
|
|
} else {
|
||
|
|
setShowNavbar(true);
|
||
|
|
}
|
||
|
|
|
||
|
|
setScrolled(currentScroll > 30);
|
||
|
|
setLastScrollY(currentScroll);
|
||
|
|
};
|
||
|
|
|
||
|
|
window.addEventListener("scroll", handleScroll, { passive: true });
|
||
|
|
return () => window.removeEventListener("scroll", handleScroll);
|
||
|
|
}, [lastScrollY]);
|
||
|
|
|
||
|
|
const navLinks = [
|
||
|
|
{ label: "Home", href: "#home" },
|
||
|
|
{ label: "About Us", href: "#about" },
|
||
|
|
{ label: "Benefits", href: "#benefits" },
|
||
|
|
{ label: "How it works", href: "/#how-it-works" },
|
||
|
|
{ label: "FAQ", href: "#faq" },
|
||
|
|
];
|
||
|
|
|
||
|
|
return (
|
||
|
|
<header
|
||
|
|
ref={navbarRef}
|
||
|
|
className={`tab:block fixed top-0 right-0 left-0 z-50 sm:hidden ${showNavbar ? "translate-y-0" : "-translate-y-full"} ${
|
||
|
|
scrolled
|
||
|
|
? "top-0 border-white/30 bg-white/40 shadow-xs backdrop-blur-md"
|
||
|
|
: "top-6 border-transparent bg-transparent"
|
||
|
|
} `.trim()}
|
||
|
|
>
|
||
|
|
<nav className="mx-auto flex h-[75px] w-full max-w-[1420px] items-center justify-between px-6 py-3 transition-all duration-300">
|
||
|
|
{/* Logo */}
|
||
|
|
<div
|
||
|
|
onClick={() => startTransition(`/`)}
|
||
|
|
className="h-10 w-36 cursor-pointer"
|
||
|
|
>
|
||
|
|
<Image
|
||
|
|
src={
|
||
|
|
scrolled
|
||
|
|
? "/images/svg/dark-logo.svg"
|
||
|
|
: "/images/svg/whispering-logo.svg"
|
||
|
|
}
|
||
|
|
width={144}
|
||
|
|
height={40}
|
||
|
|
alt="Whispering Tree"
|
||
|
|
className="h-full w-full object-contain"
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* Desktop Links */}
|
||
|
|
<div className="tab:flex hidden">
|
||
|
|
<ul className="flex items-center gap-6">
|
||
|
|
{navLinks.map((link) => (
|
||
|
|
<li key={link.href} className="flex items-center justify-center">
|
||
|
|
<SmoothScrollLink href={link.href} scrolled={scrolled}>
|
||
|
|
{link.label}
|
||
|
|
</SmoothScrollLink>
|
||
|
|
</li>
|
||
|
|
))}
|
||
|
|
</ul>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* CTA */}
|
||
|
|
<Button text="Book a Demo" />
|
||
|
|
</nav>
|
||
|
|
</header>
|
||
|
|
);
|
||
|
|
};
|
||
|
|
|
||
|
|
export default Navbar;
|