227 lines
7.9 KiB
TypeScript
227 lines
7.9 KiB
TypeScript
"use client";
|
|
|
|
import React, { useState, useEffect } from "react";
|
|
import Link from "next/link";
|
|
import { Button } from "./button";
|
|
import { Sheet, SheetContent, SheetTrigger, SheetTitle } from "./sheet";
|
|
import { Menu, X, ChevronDown } from "lucide-react";
|
|
import { HoverCard, HoverCardContent, HoverCardTrigger } from "./hover-card";
|
|
import { usePathname } from "next/navigation";
|
|
|
|
const NavBar = () => {
|
|
const [isScrolled, setIsScrolled] = useState(false);
|
|
const [isOpen, setIsOpen] = useState(false);
|
|
const pathname = usePathname();
|
|
|
|
useEffect(() => {
|
|
const handleScroll = () => {
|
|
setIsScrolled(window.scrollY > 10);
|
|
};
|
|
|
|
window.addEventListener("scroll", handleScroll);
|
|
return () => window.removeEventListener("scroll", handleScroll);
|
|
}, []);
|
|
|
|
// For static export, we need to manually add the mobile menu toggle functionality
|
|
useEffect(() => {
|
|
const toggleButton = document.querySelector('[aria-haspopup="dialog"]');
|
|
const sheet = document.querySelector('[role="dialog"]');
|
|
|
|
if (toggleButton && sheet) {
|
|
const handleToggle = () => {
|
|
setIsOpen(!isOpen);
|
|
};
|
|
|
|
toggleButton.addEventListener('click', handleToggle);
|
|
|
|
return () => {
|
|
toggleButton.removeEventListener('click', handleToggle);
|
|
};
|
|
}
|
|
}, [isOpen]);
|
|
|
|
const navLinks = [
|
|
{ label: "Home", href: "/" },
|
|
{
|
|
label: "Services",
|
|
href: "/services",
|
|
submenu: [
|
|
{ label: "Hardware Solutions", href: "/services/hardware-solutions" },
|
|
{ label: "FOSS Support", href: "/services/foss-support" },
|
|
{ label: "Data Services", href: "/services/data-services" },
|
|
]
|
|
},
|
|
{ label: "About", href: "#about" },
|
|
{ label: "Contact", href: "#contact" },
|
|
];
|
|
|
|
const isActive = (href: string) => {
|
|
if (href === '/') {
|
|
return pathname === href;
|
|
}
|
|
return pathname?.startsWith(href);
|
|
};
|
|
|
|
const handleMenuToggle = () => {
|
|
setIsOpen(!isOpen);
|
|
};
|
|
|
|
return (
|
|
<header
|
|
className={`fixed top-0 left-0 right-0 z-50 transition-all duration-300 ${
|
|
isScrolled
|
|
? "bg-netbirdDark/90 backdrop-blur-md py-3 shadow-md"
|
|
: "bg-transparent py-5"
|
|
}`}
|
|
>
|
|
<div className="container mx-auto flex items-center justify-between">
|
|
<Link href="/" className="flex items-center">
|
|
<span className="text-2xl font-bold text-white">
|
|
<span className="text-netbirdOrange">DWD</span> Consultancy
|
|
</span>
|
|
</Link>
|
|
|
|
{/* Desktop Navigation */}
|
|
<nav className="hidden md:flex items-center gap-6">
|
|
{navLinks.map((link, index) => (
|
|
link.submenu ? (
|
|
<HoverCard key={index} openDelay={0} closeDelay={100}>
|
|
<HoverCardTrigger asChild>
|
|
<div className="relative group">
|
|
<Link
|
|
href={link.href}
|
|
className={`text-sm flex items-center gap-1 ${
|
|
isActive(link.href)
|
|
? "text-netbirdOrange"
|
|
: "text-white/80 hover:text-netbirdOrange transition-colors"
|
|
}`}
|
|
>
|
|
{link.label}
|
|
<ChevronDown className="h-4 w-4" />
|
|
</Link>
|
|
</div>
|
|
</HoverCardTrigger>
|
|
<HoverCardContent
|
|
className="w-64 bg-[#0d1324] border border-white/10 p-0 shadow-xl"
|
|
>
|
|
<div className="flex flex-col py-2">
|
|
{link.submenu.map((sublink, subIndex) => (
|
|
<Link
|
|
key={subIndex}
|
|
href={sublink.href}
|
|
className={`text-sm px-4 py-2 hover:bg-white/5 ${
|
|
isActive(sublink.href)
|
|
? "text-netbirdOrange"
|
|
: "text-white/80 hover:text-netbirdOrange"
|
|
}`}
|
|
>
|
|
{sublink.label}
|
|
</Link>
|
|
))}
|
|
</div>
|
|
</HoverCardContent>
|
|
</HoverCard>
|
|
) : (
|
|
<Link
|
|
key={index}
|
|
href={link.href}
|
|
className={`text-sm ${
|
|
isActive(link.href)
|
|
? "text-netbirdOrange"
|
|
: "text-white/80 hover:text-netbirdOrange transition-colors"
|
|
}`}
|
|
>
|
|
{link.label}
|
|
</Link>
|
|
)
|
|
))}
|
|
<Link href="/contact">
|
|
<Button className="bg-netbirdOrange hover:bg-netbirdOrange/90 text-white">
|
|
Get Started
|
|
</Button>
|
|
</Link>
|
|
</nav>
|
|
|
|
{/* Mobile Navigation */}
|
|
<Sheet open={isOpen} onOpenChange={setIsOpen}>
|
|
<SheetTrigger asChild className="md:hidden">
|
|
<Button
|
|
variant="ghost"
|
|
size="icon"
|
|
className="text-white"
|
|
onClick={handleMenuToggle}
|
|
>
|
|
<Menu className="h-6 w-6" />
|
|
<span className="sr-only">Toggle menu</span>
|
|
</Button>
|
|
</SheetTrigger>
|
|
<SheetContent
|
|
side="right"
|
|
className="w-[300px] sm:w-[400px] bg-netbirdDark border-netbirdDark"
|
|
>
|
|
<SheetTitle className="sr-only">Navigation Menu</SheetTitle>
|
|
<div className="flex flex-col h-full">
|
|
<div className="flex justify-between items-center py-4">
|
|
<span className="text-xl font-bold text-white">
|
|
<span className="text-netbirdOrange">DWD</span> Consultancy
|
|
</span>
|
|
<Button
|
|
variant="ghost"
|
|
size="icon"
|
|
onClick={() => setIsOpen(false)}
|
|
>
|
|
<X className="h-6 w-6 text-white" />
|
|
</Button>
|
|
</div>
|
|
<nav className="flex flex-col gap-4 mt-8">
|
|
{navLinks.map((link, index) => (
|
|
<div key={index}>
|
|
<Link
|
|
href={link.href}
|
|
className={`text-lg ${
|
|
isActive(link.href)
|
|
? "text-netbirdOrange"
|
|
: "text-white/80 hover:text-netbirdOrange"
|
|
} py-2 transition-colors flex items-center justify-between`}
|
|
onClick={() => !link.submenu && setIsOpen(false)}
|
|
>
|
|
{link.label}
|
|
{link.submenu && <ChevronDown className="h-4 w-4" />}
|
|
</Link>
|
|
|
|
{link.submenu && (
|
|
<div className="pl-4 mt-2 border-l border-white/10 space-y-2">
|
|
{link.submenu.map((sublink, subIndex) => (
|
|
<Link
|
|
key={subIndex}
|
|
href={sublink.href}
|
|
className={`block text-base ${
|
|
isActive(sublink.href)
|
|
? "text-netbirdOrange"
|
|
: "text-white/70 hover:text-netbirdOrange"
|
|
} py-1 transition-colors`}
|
|
onClick={() => setIsOpen(false)}
|
|
>
|
|
{sublink.label}
|
|
</Link>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
))}
|
|
<Link href="/contact" onClick={() => setIsOpen(false)}>
|
|
<Button className="bg-netbirdOrange hover:bg-netbirdOrange/90 text-white mt-4 w-full">
|
|
Get Started
|
|
</Button>
|
|
</Link>
|
|
</nav>
|
|
</div>
|
|
</SheetContent>
|
|
</Sheet>
|
|
</div>
|
|
</header>
|
|
);
|
|
};
|
|
|
|
export default NavBar;
|