diff --git a/src/components/layout/Header.tsx b/src/components/layout/Header.tsx index 7926384..b19fc83 100644 --- a/src/components/layout/Header.tsx +++ b/src/components/layout/Header.tsx @@ -1,6 +1,6 @@ "use client"; -import { useState, useEffect } from 'react'; +import { useState, useEffect, useRef } from 'react'; import Link from 'next/link'; import { usePathname } from 'next/navigation'; import { Button } from '@/components/ui/button'; @@ -11,8 +11,18 @@ const Header = () => { const [isMenuOpen, setIsMenuOpen] = useState(false); const [dropdownOpen, setDropdownOpen] = useState(null); const pathname = usePathname(); + const closeTimeoutRef = useRef | null>(null); + + const openDropdown = (name: string) => { + if (closeTimeoutRef.current) clearTimeout(closeTimeoutRef.current); + setDropdownOpen(name); + }; + + const scheduleCloseDropdown = () => { + if (closeTimeoutRef.current) clearTimeout(closeTimeoutRef.current); + closeTimeoutRef.current = setTimeout(() => setDropdownOpen(null), 150); + }; - // Close dropdown when clicking outside useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if (dropdownOpen && !(event.target as Element).closest('.dropdown-container')) { @@ -28,6 +38,7 @@ const Header = () => { { name: 'Education', href: '/education', + hasLandingPage: true, dropdown: [ { name: 'Private Bitcoin Briefing', href: '/education/private-bitcoin-briefing' }, { name: 'Bitcoin Executive Masterclass', href: '/education/bitcoin-for-executives' }, @@ -37,6 +48,7 @@ const Header = () => { { name: 'Research', href: '/research', + hasLandingPage: true, dropdown: [ { name: 'Bitcoin Intelligence Briefs', href: '/research/intelligence-briefs' }, { name: 'Bitcoin Research Quarterly', href: '/research/resq-package' }, @@ -78,28 +90,51 @@ const Header = () => {
{navigation.map((item) => ( 'dropdown' in item ? ( -
- +
openDropdown(item.name)} + onMouseLeave={scheduleCloseDropdown} + > + {'hasLandingPage' in item ? ( + openDropdown(item.name)} + className={`flex items-center text-sm font-semibold transition-colors hover:text-primary-brand ${isActive(item.href) || item.dropdown?.some(sub => isActive(sub.href)) ? 'text-primary-brand' : 'text-gray-600' + }`} + > + {item.name} + + + ) : ( + + )} {dropdownOpen === item.name && item.dropdown && ( -
- {item.dropdown.map((subItem) => ( - setDropdownOpen(null)} - > - {subItem.name} - - ))} +
+
+ {item.dropdown.map((subItem) => ( + setDropdownOpen(null)} + > + {subItem.name} + + ))} +
)}
@@ -149,10 +184,21 @@ const Header = () => { {navigation.map((item) => ( 'dropdown' in item ? (
-
isActive(sub.href)) ? 'text-primary-brand' : 'text-gray-600' - }`}> - {item.name} -
+ {'hasLandingPage' in item ? ( + setIsMenuOpen(false)} + className={`block px-3 py-2 text-base font-semibold transition-colors hover:text-primary-brand ${isActive(item.href) || item.dropdown?.some(sub => isActive(sub.href)) ? 'text-primary-brand' : 'text-gray-600' + }`} + > + {item.name} + + ) : ( +
isActive(sub.href)) ? 'text-primary-brand' : 'text-gray-600' + }`}> + {item.name} +
+ )}
{item.dropdown?.map((subItem) => (