@@ -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