navbar-menu.tsx
1 "use client"; 2 import React from "react"; 3 import { motion } from "framer-motion"; 4 import Link from "next/link"; 5 import Image from "next/image"; 6 7 const transition = { 8 type: "spring", 9 mass: 0.5, 10 damping: 11.5, 11 stiffness: 100, 12 restDelta: 0.001, 13 restSpeed: 0.001, 14 }; 15 16 export const MenuItem = ({ 17 setActive, 18 active, 19 item, 20 children, 21 }: { 22 setActive: (item: string) => void; 23 active: string | null; 24 item: string; 25 children?: React.ReactNode; 26 }) => { 27 return ( 28 <div onMouseEnter={() => setActive(item)} className="relative "> 29 <motion.p 30 transition={{ duration: 0.3 }} 31 className="cursor-pointer text-black hover:opacity-[0.9] dark:text-white" 32 > 33 {item} 34 </motion.p> 35 {active !== null && ( 36 <motion.div 37 initial={{ opacity: 0, scale: 0.85, y: 10 }} 38 animate={{ opacity: 1, scale: 1, y: 0 }} 39 transition={transition} 40 > 41 {active === item && ( 42 <div className="absolute top-[calc(100%_+_1.7rem)] left-1/2 transform -translate-x-1/2"> 43 <motion.div 44 transition={transition} 45 layoutId="active" // layoutId ensures smooth animation 46 className="bg-white dark:bg-black backdrop-blur-sm rounded-2xl overflow-hidden border border-black/[0.2] dark:border-white/[0.2] shadow-xl" 47 > 48 <motion.div 49 layout // layout ensures smooth animation 50 className="w-max h-full p-4" 51 > 52 {children} 53 </motion.div> 54 </motion.div> 55 </div> 56 )} 57 </motion.div> 58 )} 59 </div> 60 ); 61 }; 62 63 export const Menu = ({ 64 setActive, 65 children, 66 }: { 67 setActive: (item: string | null) => void; 68 children: React.ReactNode; 69 }) => { 70 return ( 71 <nav 72 onMouseLeave={() => setActive(null)} // resets the state 73 className="relative rounded-full boder border-transparent dark:bg-black dark:border-white/[0.2] bg-white shadow-input flex justify-center space-x-4 px-8 py-6 " 74 > 75 {children} 76 </nav> 77 ); 78 }; 79 80 export const ProductItem = ({ 81 title, 82 description, 83 href, 84 src, 85 }: { 86 title: string; 87 description: string; 88 href: string; 89 src: string; 90 }) => { 91 return ( 92 <Link href={href} className="flex space-x-2"> 93 <Image 94 src={src} 95 width={140} 96 height={70} 97 alt={title} 98 className="flex-shrink-0 rounded-md shadow-2xl" 99 /> 100 <div> 101 <h4 className="text-xl font-bold mb-1 text-black dark:text-white"> 102 {title} 103 </h4> 104 <p className="text-neutral-700 text-sm max-w-[10rem] dark:text-neutral-300"> 105 {description} 106 </p> 107 </div> 108 </Link> 109 ); 110 }; 111 112 export const HoveredLink = ({ children, ...rest }: any) => { 113 return ( 114 <Link 115 {...rest} 116 className="text-neutral-700 dark:text-neutral-200 hover:text-black " 117 > 118 {children} 119 </Link> 120 ); 121 };