Anime Navbar
Anime Navbar is a React and Tailwind CSS navigation component written for NedDev and yours to ship. Copy it and paste it into your project.
NedDev
navigation
What it is
Anime Navbar is a React and Tailwind CSS navigation component written for NedDev and yours to ship. Copy it and paste it into your project.
How to use it
Open it in the catalogue, press copy, and paste it into your project. The prompt you copy carries the code and the rules that tell your agent to reproduce it without changing anything.
Four free copies a week. No card.
Needs
npm i framer-motion lucide-react next
Licence
This component was written for this catalogue. It is yours to ship in client work and in products you sell, under the terms of use.
Anime Navbar
"use client"
import React, { useEffect, useState } from "react"
import { motion, AnimatePresence } from "framer-motion"
import Link from "next/link"
import { usePathname } from "next/navigation"
import { LucideIcon } from "lucide-react"
import { cn } from "@/lib/utils"
interface NavItem {
name: string
url: string
icon: LucideIcon
}
interface NavBarProps {
items: NavItem[]
className?: string
defaultActive?: string
}
export function AnimeNavBar({ items, className, defaultActive = "Home" }: NavBarProps) {
const pathname = usePathname()
const [mounted, setMounted] = useState(false)
const [hoveredTab, setHoveredTab] = useState<string | null>(null)
const [activeTab, setActiveTab] = useState<string>(defaultActive)
const [isMobile, setIsMobile] = useState(false)
useEffect(() => {
setMounted(true)
}, [])
useEffect(() => {
const handleResize = () => {
setIsMobile(window.innerWidth < 768)
}
handleResize()
window.addEventListener("resize", handleResize)
return () => window.removeEventListener("resize", handleResize)
}, [])
if (!mounted) return null
return (
<div className="fixed top-5 left-0 right-0 z-[9999]">
<div className="flex justify-center pt-6">
<motion.div
className="flex items-center gap-3 bg-black/50 border border-white/10 backdrop-blur-lg py-2 px-2 rounded-full shadow-lg relative"
initial={{ y: -20, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
transition={{
type: "spring",
stiffness: 260,
damping: 20,
}}
>
{items.map((item) => {
const Icon = item.icon
const isActive = activeTab === item.name
const isHovered = hoveredTab === item.name
return (
<Link
key={item.name}
href={item.url}
onClick={(e) => {
e.preventDefault()
setActiveTab(item.name)
}}
onMouseEnter={() => setHoveredTab(item.name)}
onMouseLeave={() => setHoveredTab(null)}
className={cn(
"relative cursor-pointer text-sm font-semibold px-6 py-3 rounded-full transition-all duration-300",
"text-white/70 hover:text-white",
isActive && "text-white"
)}
>
{isActive && (
<motion.div
className="absolute inset-0 rounded-full -z-10 overflow-hidden"
initial={{ opacity: 0 }}
animate={{
opacity: [0.3, 0.5, 0.3],
scale: [1, 1.03, 1]
}}
transition={{
duration: 2,
repeat: Infinity,
ease: "easeInOut"
}}
>
<div className="absolute inset-0 bg-primary/25 rounded-full blur-md" />
<div className="absolute inset-[-4px] bg-primary/20 rounded-full blur-xl" />
<div className="absolute inset-[-8px] bg-primary/15 rounded-full blur-2xl" />
<div className="absolute inset-[-12px] bg-primary/5 rounded-full blur-3xl" />
<div
className="absolute inset-0 bg-gradient-to-r from-primary/0 via-primary/20 to-primary/0"
style={{
animation: "shine 3s ease-in-out infinite"
}}
/>
</motion.div>
)}
<motion.span
className="hidden md:inline relative z-10"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.2 }}
>
{item.name}
</motion.span>
<motion.span
className="md:hidden relative z-10"
whileHover={{ scale: 1.2 }}
whileTap={{ scale: 0.9 }}
>
<Icon size={18} strokeWidth={2.5} />
</motion.span>
<AnimatePresence>
{isHovered && !isActive && (
<motion.div
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.8 }}
className="absolute inset-0 bg-white/10 rounded-full -z-10"
/>
)}
</AnimatePresence>
{isActive && (
<motion.div
layoutId="anime-mascot"
className="absolute -top-12 left-1/2 -translate-x-1/2 pointer-events-none"
initial={false}
transition={{
type: "spring",
stiffness: 300,
damping: 30,
}}
>
<div className="relative w-12 h-12">
<motion.div
className="absolute w-10 h-10 bg-white rounded-full left-1/2 -translate-x-1/2"
animate={
hoveredTab ? {
scale: [1, 1.1, 1],
rotate: [0, -5, 5, 0],
transition: {
duration: 0.5,
ease: "easeInOut"
}
} : {
y: [0, -3, 0],
transition: {
duration: 2,
repeat: Infinity,
ease: "easeInOut"
}
}
}
>
<motion.div
className="absolute w-2 h-2 bg-black rounded-full"
animate={
hoveredTab ? {
scaleY: [1, 0.2, 1],
transition: {
duration: 0.2,
times: [0, 0.5, 1]
}
} : {}
}
style={{ left: '25%', top: '40%' }}
/>
<motion.div
className="absolute w-2 h-2 bg-black rounded-full"
animate={
hoveredTab ? {
scaleY: [1, 0.2, 1],
transition: {
duration: 0.2,
times: [0, 0.5, 1]
}
} : {}
}
style={{ right: '25%', top: '40%' }}
/>
<motion.div
className="absolute w-2 h-1.5 bg-pink-300 rounded-full"
animate={{
opacity: hoveredTab ? 0.8 : 0.6
}}
style={{ left: '15%', top: '55%' }}
/>
<motion.div
className="absolute w-2 h-1.5 bg-pink-300 rounded-full"
animate={{
opacity: hoveredTab ? 0.8 : 0.6
}}
style={{ right: '15%', top: '55%' }}
/>
<motion.div
className="absolute w-4 h-2 border-b-2 border-black rounded-full"
animate={
hoveredTab ? {
scaleY: 1.5,
y: -1
} : {
scaleY: 1,
y: 0
}
}
style={{ left: '30%', top: '60%' }}
/>
<AnimatePresence>
{hoveredTab && (
<>
<motion.div
initial={{ opacity: 0, scale: 0 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0 }}
className="absolute -top-1 -right-1 w-2 h-2 text-yellow-300"
>
✨
</motion.div>
<motion.div
initial={{ opacity: 0, scale: 0 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0 }}
transition={{ delay: 0.1 }}
className="absolute -top-2 left-0 w-2 h-2 text-yellow-300"
>
✨
</motion.div>
</>
)}
</AnimatePresence>
</motion.div>
<motion.div
className="absolute -bottom-1 left-1/2 w-4 h-4 -translate-x-1/2"
animate={
hoveredTab ? {
y: [0, -4, 0],
transition: {
duration: 0.3,
repeat: Infinity,
repeatType: "reverse"
}
} : {
y: [0, 2, 0],
transition: {
duration: 1,
repeat: Infinity,
ease: "easeInOut",
delay: 0.5
}
}
}
>
<div className="w-full h-full bg-white rotate-45 transform origin-center" />
</motion.div>
</div>
</motion.div>
)}
</Link>
)
})}
</motion.div>
</div>
</div>
)
}