11import { memo } from 'react' ;
22
3- import { motion } from 'framer-motion' ;
4- import { UserCircle , X } from 'lucide-react' ;
3+ import { UserCircle , X } from '@/assets/icons' ;
54
6- import { Logo } from '@/components/layout' ;
7-
8- import { NavbarDesktopDropdown } from './parts/NavbarDesktopDropdown' ;
9- import { NavbarMobileMenu } from './parts/NavbarMobileMenu' ;
10-
11- /** Props for the `Navbar` shell component. */
5+ import { Logo } from '@/shared/ui' ;
6+ import { NavbarDesktopMenu , NavbarMobileMenu } from './NavbarMenu' ;
127interface NavbarProps {
138 rightSlot ?: React . ReactNode ;
149 isMobileMenuOpen : boolean ;
1510 setIsMobileMenuOpen : React . Dispatch < React . SetStateAction < boolean > > ;
1611 isAuthenticated : boolean ;
17- isDropdownOpen : boolean ;
18- setIsDropdownOpen : React . Dispatch < React . SetStateAction < boolean > > ;
12+ isDesktopDropdownOpen : boolean ;
13+ setIsDesktopDropdownOpen : React . Dispatch < React . SetStateAction < boolean > > ;
1914 dropdownRef : React . RefObject < HTMLDivElement | null > ;
2015 handleLogoClick : ( ) => void ;
2116 toggleMobileMenu : ( ) => void ;
@@ -27,89 +22,80 @@ function Navbar({
2722 isMobileMenuOpen,
2823 setIsMobileMenuOpen,
2924 isAuthenticated,
30- isDropdownOpen ,
31- setIsDropdownOpen ,
25+ isDesktopDropdownOpen ,
26+ setIsDesktopDropdownOpen ,
3227 dropdownRef,
3328 handleLogoClick,
3429 toggleMobileMenu,
3530 handleSignOut
3631} : NavbarProps ) {
32+ const toggleButtonClass = ( isOpen : boolean ) =>
33+ `p-2 min-h-11 min-w-11 flex items-center justify-center rounded-lg transition-colors duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent ${
34+ isOpen
35+ ? 'bg-surface-elevated text-accent'
36+ : 'text-text-secondary hover:text-text-primary hover:bg-surface-hover active:bg-surface-elevated'
37+ } `;
38+
3739 return (
38- < >
39- < motion . nav
40- initial = { { opacity : 0 , y : - 20 } }
41- animate = { { opacity : 1 , y : 0 } }
42- transition = { { duration : 0.6 , ease : [ 0.22 , 1 , 0.36 , 1 ] } }
43- className = "navbar-shell fixed top-0 left-0 right-0 z-50 transition-all duration-300"
44- >
45- < div className = "relative z-50 bg-surface" >
46- < div className = "page-container" >
47- < div className = "flex justify-between items-center py-3 min-h-12 sm:min-h-14 lg:min-h-16" >
48- < button
49- type = "button"
50- onClick = { handleLogoClick }
51- aria-label = "ChessVision home"
52- className = "flex items-center gap-2 rounded-lg transition-colors duration-200 text-text-primary hover:text-text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent"
53- >
54- < div className = "flex items-center gap-2" >
55- < Logo className = "w-8 h-8 sm:w-10 sm:h-10 lg:w-12 lg:h-12 object-contain" />
56- < div className = "hidden lg:block" >
57- < span className = "font-display font-bold text-xl xs:text-2xl sm:text-3xl leading-tight text-text-primary" >
58- Chess
59- </ span >
60- < span className = "font-display font-bold text-xl xs:text-2xl sm:text-3xl text-text-primary leading-tight " >
61- Vision
62- </ span >
63- </ div >
40+ < nav className = "fixed top-0 left-0 right-0 z-50 pt-[max(0px, env(safe-area-inset-top))] transition-all duration-300 animate-navbar-in" >
41+ < div className = "relative z-50 bg-surface" >
42+ < div className = "page-container" >
43+ < div className = "flex justify-between items-center py-3 min-h-12 sm:min-h-14 lg:min-h-16" >
44+ < button
45+ type = "button"
46+ onClick = { handleLogoClick }
47+ aria-label = "ChessViewer home"
48+ className = "flex items-center gap-2 rounded-lg transition-colors duration-200 text-text-primary hover:text-text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent"
49+ >
50+ < div className = "flex items-center gap-2" >
51+ < Logo className = "w-8 h-8 sm:w-10 sm:h-10 lg:w-12 lg:h-12 object-contain" />
52+ < div className = "hidden lg:block" >
53+ < span className = "font-display font-bold text-xl xs:text-2xl sm:text-3xl leading-tight text-text-primary" >
54+ ChessViewer
55+ </ span >
6456 </ div >
65- </ button >
66-
67- < div className = "hidden lg:flex items-center gap-2" >
68- { rightSlot }
69-
70- < NavbarDesktopDropdown
71- isAuthenticated = { isAuthenticated }
72- isDropdownOpen = { isDropdownOpen }
73- setIsDropdownOpen = { setIsDropdownOpen }
74- dropdownRef = { dropdownRef }
75- handleSignOut = { handleSignOut }
76- />
7757 </ div >
58+ </ button >
7859
79- < div className = "flex lg:hidden items-center gap-2" >
80- { rightSlot }
60+ < div className = "hidden lg:flex items-center gap-2" >
61+ { rightSlot }
62+ < NavbarDesktopMenu
63+ isAuthenticated = { isAuthenticated }
64+ isDesktopDropdownOpen = { isDesktopDropdownOpen }
65+ setIsDesktopDropdownOpen = { setIsDesktopDropdownOpen }
66+ dropdownRef = { dropdownRef }
67+ handleSignOut = { handleSignOut }
68+ />
69+ </ div >
8170
82- < button
83- type = "button"
84- onClick = { toggleMobileMenu }
85- className = { `p-2 min-h-11 min-w-11 flex items-center justify-center rounded-lg transition-colors duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent ${
86- isMobileMenuOpen
87- ? 'bg-surface-elevated text-accent'
88- : 'text-text-secondary hover:text-text-primary hover:bg-surface-hover active:bg-surface-elevated'
89- } `}
90- aria-label = "Account menu"
91- aria-haspopup = "menu"
92- aria-expanded = { isMobileMenuOpen }
93- >
94- { isMobileMenuOpen ? (
95- < X className = "w-6 h-6" aria-hidden = "true" />
96- ) : (
97- < UserCircle className = "w-6 h-6" aria-hidden = "true" />
98- ) }
99- </ button >
100- </ div >
71+ < div className = "flex lg:hidden items-center gap-2" >
72+ { rightSlot }
73+ < button
74+ type = "button"
75+ onClick = { toggleMobileMenu }
76+ className = { toggleButtonClass ( isMobileMenuOpen ) }
77+ aria-label = "Account menu"
78+ aria-haspopup = "menu"
79+ aria-expanded = { isMobileMenuOpen }
80+ >
81+ { isMobileMenuOpen ? (
82+ < X className = "w-6 h-6" aria-hidden = "true" />
83+ ) : (
84+ < UserCircle className = "w-6 h-6" aria-hidden = "true" />
85+ ) }
86+ </ button >
10187 </ div >
10288 </ div >
10389 </ div >
90+ </ div >
10491
105- < NavbarMobileMenu
106- isOpen = { isMobileMenuOpen }
107- isAuthenticated = { isAuthenticated }
108- setIsMobileMenuOpen = { setIsMobileMenuOpen }
109- handleSignOut = { handleSignOut }
110- />
111- </ motion . nav >
112- </ >
92+ < NavbarMobileMenu
93+ isOpen = { isMobileMenuOpen }
94+ isAuthenticated = { isAuthenticated }
95+ setIsMobileMenuOpen = { setIsMobileMenuOpen }
96+ handleSignOut = { handleSignOut }
97+ />
98+ </ nav >
11399 ) ;
114100}
115101
0 commit comments