Skip to content

Commit cfaf64e

Browse files
--navbar component update
1 parent 69ce944 commit cfaf64e

File tree

1 file changed

+123
-37
lines changed

1 file changed

+123
-37
lines changed

components/ui/anime-navbar.tsx

Lines changed: 123 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -27,34 +27,56 @@ export function AnimeNavBar({
2727
}: NavBarProps) {
2828
const router = useRouter()
2929
const pathname = usePathname()
30-
30+
31+
// State Management
3132
const [mounted, setMounted] = useState(false)
3233
const [hoveredTab, setHoveredTab] = useState<string | null>(null)
3334
const [activeTab, setActiveTab] = useState<string>(defaultActive)
35+
const [isMobile, setIsMobile] = useState(false)
3436

37+
// Mounted Effect
3538
useEffect(() => {
3639
setMounted(true)
40+
const handleResize = () => setIsMobile(window.innerWidth < 768)
41+
handleResize()
42+
window.addEventListener("resize", handleResize)
43+
return () => window.removeEventListener("resize", handleResize)
3744
}, [])
3845

46+
// Pathname Change Effect
3947
useEffect(() => {
4048
const currentItem = items.find(item => item.url === pathname)
4149
if (currentItem) {
4250
setActiveTab(currentItem.name)
4351
}
4452
}, [pathname, items])
4553

54+
// Prevent rendering before client-side mount
4655
if (!mounted) return null
4756

57+
// Navigation Handler
4858
const handleNavigation = (item: NavItem) => {
4959
setActiveTab(item.name)
5060
router.push(item.url)
5161
}
5262

5363
return (
54-
<div className={cn("fixed top-5 left-0 right-0 z-[9999]", className)}>
55-
<div className="flex justify-center pt-6">
64+
<div
65+
className={cn(
66+
// Lower on mobile for mascot space, tighter on desktop
67+
"fixed left-0 right-0 z-[9999]",
68+
isMobile ? "top-3" : "top-5",
69+
className
70+
)}
71+
>
72+
<div className={cn("flex justify-center", isMobile ? "pt-2" : "pt-6")}>
5673
<motion.div
57-
className="flex items-center gap-2 bg-black/50 border border-white/10 backdrop-blur-lg py-2 px-2 rounded-full shadow-lg relative overflow-x-auto scrollbar-thin scrollbar-thumb-gray-700 scrollbar-track-transparent max-w-full"
74+
className={cn(
75+
"flex items-center bg-black/50 border border-white/10 backdrop-blur-lg rounded-full shadow-lg relative",
76+
isMobile
77+
? "gap-1 py-1 px-1 max-w-[95vw] overflow-x-auto"
78+
: "gap-3 py-2 px-2"
79+
)}
5880
initial={{ y: -20, opacity: 0 }}
5981
animate={{ y: 0, opacity: 1 }}
6082
transition={{
@@ -75,7 +97,10 @@ export function AnimeNavBar({
7597
onMouseEnter={() => setHoveredTab(item.name)}
7698
onMouseLeave={() => setHoveredTab(null)}
7799
className={cn(
78-
"relative cursor-pointer text-xs sm:text-sm font-semibold px-3 sm:px-6 py-2 sm:py-3 rounded-full transition-all duration-300 whitespace-nowrap",
100+
"relative cursor-pointer font-semibold rounded-full transition-all duration-300 whitespace-nowrap select-none",
101+
isMobile
102+
? "text-base px-3 py-2"
103+
: "text-sm px-6 py-3",
79104
"text-white/70 hover:text-white",
80105
isActive && "text-white"
81106
)}
@@ -101,17 +126,32 @@ export function AnimeNavBar({
101126
<div className="absolute inset-[-12px] bg-primary/5 rounded-full blur-3xl" />
102127
<div
103128
className="absolute inset-0 bg-gradient-to-r from-primary/0 via-primary/20 to-primary/0"
104-
style={{ animation: "shine 3s ease-in-out infinite" }}
129+
style={{
130+
animation: "shine 3s ease-in-out infinite"
131+
}}
105132
/>
106133
</motion.div>
107134
)}
108135

109-
{/* Icon and Text always visible */}
110-
<span className="flex items-center gap-1 relative z-10">
111-
<Icon size={18} strokeWidth={2.5} />
112-
<span>{item.name}</span>
113-
</span>
136+
{/* Desktop Text */}
137+
<motion.span
138+
className="hidden md:inline relative z-10"
139+
initial={{ opacity: 0 }}
140+
animate={{ opacity: 1 }}
141+
transition={{ duration: 0.2 }}
142+
>
143+
{item.name}
144+
</motion.span>
114145

146+
{/* Mobile Icon */}
147+
<motion.span
148+
className="md:hidden relative z-10"
149+
whileHover={{ scale: 1.2 }}
150+
whileTap={{ scale: 0.9 }}
151+
>
152+
<Icon size={22} strokeWidth={2.5} />
153+
</motion.span>
154+
115155
{/* Hover Effect */}
116156
<AnimatePresence>
117157
{isHovered && !isActive && (
@@ -128,22 +168,34 @@ export function AnimeNavBar({
128168
{isActive && (
129169
<motion.div
130170
layoutId="anime-mascot"
131-
className="absolute -top-12 left-1/2 -translate-x-1/2 pointer-events-none"
171+
className={cn(
172+
"absolute left-1/2 -translate-x-1/2 pointer-events-none z-[10000]",
173+
isMobile ? "-top-4" : "-top-12"
174+
)}
132175
initial={false}
133176
transition={{
134177
type: "spring",
135178
stiffness: 300,
136179
damping: 30,
137180
}}
138181
>
139-
<div className="relative w-12 h-12">
182+
<div className={cn(
183+
"relative",
184+
isMobile ? "w-8 h-8" : "w-12 h-12"
185+
)}>
140186
<motion.div
141-
className="absolute w-10 h-10 bg-white rounded-full left-1/2 -translate-x-1/2"
187+
className={cn(
188+
"absolute bg-white rounded-full left-1/2 -translate-x-1/2",
189+
isMobile ? "w-7 h-7" : "w-10 h-10"
190+
)}
142191
animate={
143192
hoveredTab ? {
144193
scale: [1, 1.1, 1],
145194
rotate: [0, -5, 5, 0],
146-
transition: { duration: 0.5, ease: "easeInOut" }
195+
transition: {
196+
duration: 0.5,
197+
ease: "easeInOut"
198+
}
147199
} : {
148200
y: [0, -3, 0],
149201
transition: {
@@ -154,9 +206,12 @@ export function AnimeNavBar({
154206
}
155207
}
156208
>
157-
{/* Eyes */}
209+
{/* Mascot Eyes */}
158210
<motion.div
159-
className="absolute w-2 h-2 bg-black rounded-full"
211+
className={cn(
212+
"absolute bg-black rounded-full",
213+
isMobile ? "w-1 h-1" : "w-2 h-2"
214+
)}
160215
animate={
161216
hoveredTab ? {
162217
scaleY: [1, 0.2, 1],
@@ -166,10 +221,13 @@ export function AnimeNavBar({
166221
}
167222
} : {}
168223
}
169-
style={{ left: '25%', top: '40%' }}
224+
style={{ left: isMobile ? '22%' : '25%', top: '40%' }}
170225
/>
171226
<motion.div
172-
className="absolute w-2 h-2 bg-black rounded-full"
227+
className={cn(
228+
"absolute bg-black rounded-full",
229+
isMobile ? "w-1 h-1" : "w-2 h-2"
230+
)}
173231
animate={
174232
hoveredTab ? {
175233
scaleY: [1, 0.2, 1],
@@ -179,39 +237,61 @@ export function AnimeNavBar({
179237
}
180238
} : {}
181239
}
182-
style={{ right: '25%', top: '40%' }}
240+
style={{ right: isMobile ? '22%' : '25%', top: '40%' }}
183241
/>
184242

185-
{/* Blush */}
243+
{/* Mascot Blush */}
186244
<motion.div
187-
className="absolute w-2 h-1.5 bg-pink-300 rounded-full"
188-
animate={{ opacity: hoveredTab ? 0.8 : 0.6 }}
189-
style={{ left: '15%', top: '55%' }}
245+
className={cn(
246+
"absolute bg-pink-300 rounded-full",
247+
isMobile ? "w-1.5 h-0.5" : "w-2 h-1.5"
248+
)}
249+
animate={{
250+
opacity: hoveredTab ? 0.8 : 0.6
251+
}}
252+
style={{ left: isMobile ? '10%' : '15%', top: isMobile ? '55%' : '55%' }}
190253
/>
191254
<motion.div
192-
className="absolute w-2 h-1.5 bg-pink-300 rounded-full"
193-
animate={{ opacity: hoveredTab ? 0.8 : 0.6 }}
194-
style={{ right: '15%', top: '55%' }}
255+
className={cn(
256+
"absolute bg-pink-300 rounded-full",
257+
isMobile ? "w-1.5 h-0.5" : "w-2 h-1.5"
258+
)}
259+
animate={{
260+
opacity: hoveredTab ? 0.8 : 0.6
261+
}}
262+
style={{ right: isMobile ? '10%' : '15%', top: isMobile ? '55%' : '55%' }}
195263
/>
196-
197-
{/* Mouth */}
264+
265+
{/* Mascot Mouth */}
198266
<motion.div
199-
className="absolute w-4 h-2 border-b-2 border-black rounded-full"
267+
className={cn(
268+
"absolute border-b-2 border-black rounded-full",
269+
isMobile ? "w-2 h-1" : "w-4 h-2"
270+
)}
200271
animate={
201-
hoveredTab ? { scaleY: 1.5, y: -1 } : { scaleY: 1, y: 0 }
272+
hoveredTab ? {
273+
scaleY: 1.5,
274+
y: -1
275+
} : {
276+
scaleY: 1,
277+
y: 0
278+
}
202279
}
203-
style={{ left: '30%', top: '60%' }}
280+
style={{ left: isMobile ? '25%' : '30%', top: isMobile ? '62%' : '60%' }}
204281
/>
205282

206-
{/* Sparkles */}
283+
{/* Sparkle Effects */}
207284
<AnimatePresence>
208285
{hoveredTab && (
209286
<>
210287
<motion.div
211288
initial={{ opacity: 0, scale: 0 }}
212289
animate={{ opacity: 1, scale: 1 }}
213290
exit={{ opacity: 0, scale: 0 }}
214-
className="absolute -top-1 -right-1 w-2 h-2 text-yellow-300"
291+
className={cn(
292+
"absolute text-yellow-300",
293+
isMobile ? "-top-1 -right-1 w-1 h-1" : "-top-1 -right-1 w-2 h-2"
294+
)}
215295
>
216296
217297
</motion.div>
@@ -220,7 +300,10 @@ export function AnimeNavBar({
220300
animate={{ opacity: 1, scale: 1 }}
221301
exit={{ opacity: 0, scale: 0 }}
222302
transition={{ delay: 0.1 }}
223-
className="absolute -top-2 left-0 w-2 h-2 text-yellow-300"
303+
className={cn(
304+
"absolute text-yellow-300",
305+
isMobile ? "-top-2 left-0 w-1 h-1" : "-top-2 left-0 w-2 h-2"
306+
)}
224307
>
225308
226309
</motion.div>
@@ -229,9 +312,12 @@ export function AnimeNavBar({
229312
</AnimatePresence>
230313
</motion.div>
231314

232-
{/* Base */}
315+
{/* Mascot Base */}
233316
<motion.div
234-
className="absolute -bottom-1 left-1/2 w-4 h-4 -translate-x-1/2"
317+
className={cn(
318+
"absolute left-1/2 -translate-x-1/2",
319+
isMobile ? "-bottom-1 w-2 h-2" : "-bottom-1 w-4 h-4"
320+
)}
235321
animate={
236322
hoveredTab ? {
237323
y: [0, -4, 0],

0 commit comments

Comments
 (0)