feat: refactor Header with NAVIGATION_V2 and MegaDropdown integration
This commit is contained in:
@@ -7,7 +7,8 @@ import { usePathname, useSearchParams } from 'next/navigation';
|
|||||||
import { Menu, X } from 'lucide-react';
|
import { Menu, X } from 'lucide-react';
|
||||||
import { AnimatePresence, motion } from 'framer-motion';
|
import { AnimatePresence, motion } from 'framer-motion';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { COMPANY_INFO, NAVIGATION, type NavigationItem } from '@/lib/constants';
|
import { COMPANY_INFO, NAVIGATION_V2, MEGA_DROPDOWN_DATA, type NavigationItemV2 } from '@/lib/constants';
|
||||||
|
import { MegaDropdown } from '@/components/layout/mega-dropdown';
|
||||||
import { useFocusTrap } from '@/hooks/use-focus-trap';
|
import { useFocusTrap } from '@/hooks/use-focus-trap';
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
@@ -19,6 +20,7 @@ declare global {
|
|||||||
function HeaderContent() {
|
function HeaderContent() {
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const [isScrolled, setIsScrolled] = useState(false);
|
const [isScrolled, setIsScrolled] = useState(false);
|
||||||
|
const [openDropdown, setOpenDropdown] = useState<string | null>(null);
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
const focusTrapRef = useFocusTrap<HTMLDivElement>(isOpen);
|
const focusTrapRef = useFocusTrap<HTMLDivElement>(isOpen);
|
||||||
@@ -91,7 +93,7 @@ function HeaderContent() {
|
|||||||
}
|
}
|
||||||
}, [isOpen]);
|
}, [isOpen]);
|
||||||
|
|
||||||
const handleNavClick = useCallback((e: React.MouseEvent<HTMLAnchorElement>, item: NavigationItem) => {
|
const handleNavClick = useCallback((e: React.MouseEvent<HTMLAnchorElement>, item: NavigationItemV2) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
if (item.id === 'contact') {
|
if (item.id === 'contact') {
|
||||||
@@ -133,7 +135,7 @@ function HeaderContent() {
|
|||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
}, [pathname]);
|
}, [pathname]);
|
||||||
|
|
||||||
const isActive = useCallback((item: NavigationItem) => {
|
const isActive = useCallback((item: NavigationItemV2) => {
|
||||||
if (item.id === 'contact') {
|
if (item.id === 'contact') {
|
||||||
return pathname === '/contact';
|
return pathname === '/contact';
|
||||||
}
|
}
|
||||||
@@ -145,8 +147,6 @@ function HeaderContent() {
|
|||||||
return false;
|
return false;
|
||||||
}, [pathname, activeSection]);
|
}, [pathname, activeSection]);
|
||||||
|
|
||||||
const navigationItems = NAVIGATION;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<header
|
<header
|
||||||
@@ -178,7 +178,16 @@ function HeaderContent() {
|
|||||||
</StaticLink>
|
</StaticLink>
|
||||||
|
|
||||||
<nav className="hidden md:flex items-center gap-1" role="navigation" aria-label="主导航" data-testid="desktop-navigation">
|
<nav className="hidden md:flex items-center gap-1" role="navigation" aria-label="主导航" data-testid="desktop-navigation">
|
||||||
{navigationItems.map((item) => (
|
{NAVIGATION_V2.map((item) => (
|
||||||
|
item.hasDropdown ? (
|
||||||
|
<MegaDropdown
|
||||||
|
key={item.id}
|
||||||
|
label={item.label}
|
||||||
|
items={MEGA_DROPDOWN_DATA[item.dropdownKey!]}
|
||||||
|
isOpen={openDropdown === item.id}
|
||||||
|
onToggle={() => setOpenDropdown(openDropdown === item.id ? null : item.id)}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
<StaticLink
|
<StaticLink
|
||||||
key={item.id}
|
key={item.id}
|
||||||
href={item.href}
|
href={item.href}
|
||||||
@@ -205,6 +214,7 @@ function HeaderContent() {
|
|||||||
`}
|
`}
|
||||||
/>
|
/>
|
||||||
</StaticLink>
|
</StaticLink>
|
||||||
|
)
|
||||||
))}
|
))}
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
@@ -260,7 +270,7 @@ function HeaderContent() {
|
|||||||
data-testid="mobile-navigation"
|
data-testid="mobile-navigation"
|
||||||
>
|
>
|
||||||
<nav className="container-wide py-6">
|
<nav className="container-wide py-6">
|
||||||
{navigationItems.map((item, index) => (
|
{NAVIGATION_V2.map((item, index) => (
|
||||||
<motion.div
|
<motion.div
|
||||||
key={item.id}
|
key={item.id}
|
||||||
initial={{ x: 20, opacity: 0 }}
|
initial={{ x: 20, opacity: 0 }}
|
||||||
|
|||||||
Reference in New Issue
Block a user