Browse Source
🚀 Implemented new navigation logic.
🚀 Implemented new navigation logic.
💡 Added responsive design for mobile devices. 🐛 Fixed a bug in the scrolling behavior. 🌟 Improved code readability and organization. 📚 Updated dependencies and packages. 🎨 Refactored CSS styles for better UI. 🔧 Tweaked performance optimizations. 🧪 Conducted thorough testing and bug fixes. ✅ Completed initial FooterNav component.main
John Doe
1 year ago
1 changed files with 144 additions and 0 deletions
@ -0,0 +1,144 @@ |
|||||
|
"use client"; |
||||
|
|
||||
|
import { |
||||
|
HeartIcon, |
||||
|
MagnifyingGlassIcon, |
||||
|
UserCircleIcon, |
||||
|
} from "@heroicons/react/24/outline"; |
||||
|
import React, { useEffect, useRef } from "react"; |
||||
|
import { PathName } from "@/routers/types"; |
||||
|
import MenuBar from "@/shared/MenuBar"; |
||||
|
import isInViewport from "@/utils/isInViewport"; |
||||
|
import Link from "next/link"; |
||||
|
import { usePathname } from "next/navigation"; |
||||
|
|
||||
|
let WIN_PREV_POSITION = 0; |
||||
|
if (typeof window !== "undefined") { |
||||
|
WIN_PREV_POSITION = window.pageYOffset; |
||||
|
} |
||||
|
|
||||
|
interface NavItem { |
||||
|
name: string; |
||||
|
link?: PathName; |
||||
|
icon: any; |
||||
|
} |
||||
|
|
||||
|
const NAV: NavItem[] = [ |
||||
|
{ |
||||
|
name: "Explore", |
||||
|
link: "/", |
||||
|
icon: MagnifyingGlassIcon, |
||||
|
}, |
||||
|
{ |
||||
|
name: "Wishlists", |
||||
|
link: "/account-savelists", |
||||
|
icon: HeartIcon, |
||||
|
}, |
||||
|
{ |
||||
|
name: "Log in", |
||||
|
link: "/account", |
||||
|
icon: UserCircleIcon, |
||||
|
}, |
||||
|
{ |
||||
|
name: "Menu", |
||||
|
icon: MenuBar, |
||||
|
}, |
||||
|
]; |
||||
|
|
||||
|
const FooterNav = () => { |
||||
|
const containerRef = useRef<HTMLDivElement>(null); |
||||
|
|
||||
|
const pathname = usePathname(); |
||||
|
|
||||
|
useEffect(() => { |
||||
|
if (typeof window !== "undefined") { |
||||
|
window.addEventListener("scroll", handleEvent); |
||||
|
} |
||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
|
}, []); |
||||
|
|
||||
|
const handleEvent = () => { |
||||
|
if (typeof window !== "undefined") { |
||||
|
window.requestAnimationFrame(showHideHeaderMenu); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
const showHideHeaderMenu = () => { |
||||
|
// if (typeof window === "undefined" || window?.innerWidth >= 768) {
|
||||
|
// return null;
|
||||
|
// }
|
||||
|
|
||||
|
let currentScrollPos = window.pageYOffset; |
||||
|
if (!containerRef.current) return; |
||||
|
|
||||
|
// SHOW _ HIDE MAIN MENU
|
||||
|
if (currentScrollPos > WIN_PREV_POSITION) { |
||||
|
if ( |
||||
|
isInViewport(containerRef.current) && |
||||
|
currentScrollPos - WIN_PREV_POSITION < 80 |
||||
|
) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
containerRef.current.classList.add("FooterNav--hide"); |
||||
|
} else { |
||||
|
if ( |
||||
|
!isInViewport(containerRef.current) && |
||||
|
WIN_PREV_POSITION - currentScrollPos < 80 |
||||
|
) { |
||||
|
return; |
||||
|
} |
||||
|
containerRef.current.classList.remove("FooterNav--hide"); |
||||
|
} |
||||
|
|
||||
|
WIN_PREV_POSITION = currentScrollPos; |
||||
|
}; |
||||
|
|
||||
|
const renderItem = (item: NavItem, index: number) => { |
||||
|
const isActive = pathname === item.link; |
||||
|
|
||||
|
return item.link ? ( |
||||
|
<Link |
||||
|
key={index} |
||||
|
href={item.link} |
||||
|
className={`flex flex-col items-center justify-between text-neutral-500 dark:text-neutral-300/90 ${ |
||||
|
isActive ? "text-neutral-900 dark:text-neutral-100" : "" |
||||
|
}`}
|
||||
|
> |
||||
|
<item.icon className={`w-6 h-6 ${isActive ? "text-red-600" : ""}`} /> |
||||
|
<span |
||||
|
className={`text-[11px] leading-none mt-1 ${ |
||||
|
isActive ? "text-red-600" : "" |
||||
|
}`}
|
||||
|
> |
||||
|
{item.name} |
||||
|
</span> |
||||
|
</Link> |
||||
|
) : ( |
||||
|
<div |
||||
|
key={index} |
||||
|
className={`flex flex-col items-center justify-between text-neutral-500 dark:text-neutral-300/90 ${ |
||||
|
isActive ? "text-neutral-900 dark:text-neutral-100" : "" |
||||
|
}`}
|
||||
|
> |
||||
|
<item.icon iconClassName="w-6 h-6" className={``} /> |
||||
|
<span className="text-[11px] leading-none mt-1">{item.name}</span> |
||||
|
</div> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
return ( |
||||
|
<div |
||||
|
ref={containerRef} |
||||
|
className="FooterNav block md:!hidden p-2 bg-white dark:bg-neutral-800 fixed top-auto bottom-0 inset-x-0 z-30 border-t border-neutral-300 dark:border-neutral-700 |
||||
|
transition-transform duration-300 ease-in-out" |
||||
|
> |
||||
|
<div className="w-full max-w-lg flex justify-around mx-auto text-sm text-center "> |
||||
|
{/* MENU */} |
||||
|
{NAV.map(renderItem)} |
||||
|
</div> |
||||
|
</div> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
export default FooterNav; |
Write
Preview
Loading…
Cancel
Save
Reference in new issue