1- import { Link } from "react-router-dom" ;
1+ import { NavLink , Link , useLocation , useNavigate } from "react-router-dom" ;
22import { useState , useContext } from "react" ;
33import { ThemeContext } from "../context/ThemeContext" ;
4- import { Moon , Sun } from 'lucide-react' ;
5-
4+ import { Moon , Sun , Menu , X , UserPlus } from 'lucide-react' ;
65
76const Navbar : React . FC = ( ) => {
8-
97 const [ isOpen , setIsOpen ] = useState < boolean > ( false ) ;
108 const themeContext = useContext ( ThemeContext ) ;
9+ const location = useLocation ( ) ;
10+ const navigate = useNavigate ( ) ;
1111
12- if ( ! themeContext )
13- return null ;
14-
12+ if ( ! themeContext ) return null ;
1513 const { toggleTheme, mode } = themeContext ;
1614
17- return (
18- < nav className = "sticky top-0 z-50 bg-white dark:bg-gray-900 text-black dark:text-white border-b border-gray-100 dark:border-gray-800 transition-colors duration-300" >
19- < div className = "container mx-auto px-6 py-4 flex justify-between items-center" >
20- { /* Logo Section */ }
21- < Link
22- to = "/"
23- className = "text-2xl font-bold hover:text-gray-300 cursor-pointer flex items-center"
24- >
25- < img src = "/crl-icon.png" alt = "CRL Icon" className = "h-8 mr-2" />
26- GitHub Tracker
27- </ Link >
15+ // Helper function for smooth scrolling
16+ const scrollToFeatures = ( e : React . MouseEvent ) => {
17+ e . preventDefault ( ) ;
18+
19+ // If not on the home page, navigate home first, then scroll
20+ if ( location . pathname !== "/" ) {
21+ navigate ( "/" ) ;
22+ // Small timeout to allow the home page to load before scrolling
23+ setTimeout ( ( ) => {
24+ const element = document . getElementById ( "features" ) ;
25+ element ?. scrollIntoView ( { behavior : "smooth" } ) ;
26+ } , 100 ) ;
27+ } else {
28+ // If already on home page, just scroll
29+ const element = document . getElementById ( "features" ) ;
30+ element ?. scrollIntoView ( { behavior : "smooth" } ) ;
31+ }
32+ setIsOpen ( false ) ; // Close mobile menu if open
33+ } ;
2834
29- { /* Desktop Links */ }
30- < div className = "hidden md:flex space-x-6" >
31- < Link
32- to = "/"
33- className = "text-lg font-medium hover:text-gray-300 transition-all px-2 py-1 border border-transparent hover:border-gray-400 rounded"
34- >
35- Home
36- </ Link >
37- < Link
38- to = "/track"
39- className = "text-lg font-medium hover:text-gray-300 transition-all px-2 py-1 border border-transparent hover:border-gray-400 rounded"
40- >
41- Tracker
42- </ Link >
43- < Link
44- to = "/contributors"
45- className = "text-lg font-medium hover:text-gray-300 transition-all px-2 py-1 border border-transparent hover:border-gray-400 rounded"
46- >
47- Contributors
48- </ Link >
49- < Link
50- to = "/login"
51- className = "text-lg font-medium hover:text-gray-300 transition-all px-2 py-1 border border-transparent hover:border-gray-400 rounded"
52- >
53- Login
54- </ Link >
55- < button
56- onClick = { toggleTheme }
57- className = "text-sm font-semibold px-3 py-1 rounded border border-gray-500 hover:text-gray-300 hover:border-gray-300 transition duration-200"
58- >
59- { mode === "dark" ? < Sun className = "h-5 w-5" /> : < Moon className = "h-5 w-5" /> }
60- </ button >
61- </ div >
35+ const navLinkStyles = ( { isActive } : { isActive : boolean } ) =>
36+ `px-5 py-2 rounded-full text-lg font-semibold transition-all duration-300
37+ ${ isActive
38+ ? "text-blue-600 bg-blue-100/60 dark:bg-blue-900/40 shadow-sm ring-1 ring-blue-200/50 dark:ring-blue-500/20"
39+ : "text-slate-600 dark:text-gray-300 hover:text-blue-500 hover:bg-white/50 dark:hover:bg-gray-800/50"
40+ } `;
6241
63- { /* Mobile Menu Button */ }
64- < div className = "md:hidden" >
65- < button
66- onClick = { ( ) => setIsOpen ( ! isOpen ) }
67- className = "relative w-8 h-8 flex flex-col space-y-[5px] items-center group focus:outline-none"
68- >
69- < span
70- className = { `block h-[3px] w-full bg-black dark:bg-white rounded-lg transition-transform duration-300 ${
71- isOpen ? "rotate-45 translate-y-2" : ""
72- } `}
73- > </ span >
74- < span
75- className = { `block h-[3px] w-full bg-black dark:bg-white rounded-lg transition-opacity duration-300 ${
76- isOpen ? "opacity-0" : ""
77- } `}
78- > </ span >
79- < span
80- className = { `block h-[3px] w-full bg-black dark:bg-white rounded-lg transition-transform duration-300 ${
81- isOpen ? "-rotate-45 -translate-y-2" : ""
82- } `}
83- > </ span >
84- </ button >
85- </ div >
86- </ div >
42+ return (
43+ < nav className = "sticky top-0 z-50 w-full bg-indigo-50/70 dark:bg-gray-900/95 backdrop-blur-xl border-b border-indigo-100/50 dark:border-gray-800 shadow-sm transition-all duration-300" >
44+ < div className = "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8" >
45+ < div className = "flex justify-between items-center h-20" >
46+
47+ { /* 1. Logo Section */ }
48+ < Link to = "/" className = "flex items-center shrink-0 group transition-all active:scale-95" >
49+ < div className = "relative" >
50+ < img
51+ src = "/crl-icon.png"
52+ alt = "CRL Icon"
53+ className = "h-10 w-10 mr-3 drop-shadow-md group-hover:rotate-6 transition-transform duration-300"
54+ />
55+ < div className = "absolute -inset-1 bg-blue-400/20 rounded-full blur opacity-0 group-hover:opacity-100 transition-opacity" />
56+ </ div >
57+ < div className = "flex items-center tracking-tight" >
58+ < span className = "text-2xl font-extrabold text-slate-900 dark:text-white" > GitHub</ span >
59+ < span className = "text-2xl font-extrabold text-blue-600 ml-1" > Tracker</ span >
60+ </ div >
61+ </ Link >
8762
88- { /* Mobile Links */ }
89- { isOpen && (
90- < div className = "md:hidden bg-white dark:bg-gray-800 text-black dark:text-white" >
91- < div className = "space-y-4 px-6 py-4" >
92- < Link
93- to = "/"
94- className = "block text-lg font-medium hover:text-gray-300 transition-all px-2 py-1 border border-transparent hover:border-gray-400 rounded"
95- onClick = { ( ) => setIsOpen ( false ) }
96- >
97- Home
98- </ Link >
99- < Link
100- to = "/about"
101- className = "block text-lg font-medium hover:text-gray-300 transition-all px-2 py-1 border border-transparent hover:border-gray-400 rounded"
102- onClick = { ( ) => setIsOpen ( false ) }
103- >
104- About
105- </ Link >
106- < Link
107- to = "/contact"
108- className = "block text-lg font-medium hover:text-gray-300 transition-all px-2 py-1 border border-transparent hover:border-gray-400 rounded"
109- onClick = { ( ) => setIsOpen ( false ) }
63+ { /* 2. Centered Navigation */ }
64+ < div className = "hidden lg:flex items-center justify-center flex-1 space-x-1" >
65+ < NavLink to = "/" className = { navLinkStyles } > Home</ NavLink >
66+
67+ { /* Features Link - Trigger Scroll */ }
68+ < a
69+ href = "#features"
70+ onClick = { scrollToFeatures }
71+ className = "px-5 py-2 rounded-full text-lg font-semibold text-slate-600 dark:text-gray-300 hover:text-blue-500 hover:bg-white/50 dark:hover:bg-gray-800/50 transition-all duration-300"
11072 >
111- Contact
112- </ Link >
113- < Link
114- to = "/contributors"
115- className = "block text-lg font-medium hover:text-gray-300 transition-all px-2 py-1 border border-transparent hover:border-gray-400 rounded"
116- onClick = { ( ) => setIsOpen ( false ) }
73+ Features
74+ </ a >
75+
76+ < NavLink to = "/track" className = { navLinkStyles } > Tracker</ NavLink >
77+ < NavLink to = "/contributors" className = { navLinkStyles } > Contributors</ NavLink >
78+ </ div >
79+
80+ { /* 3. Right Side Actions */ }
81+ < div className = "hidden lg:flex items-center space-x-5" >
82+ < div className = "h-8 w-[1.5px] bg-indigo-200/60 dark:bg-gray-700 mx-2 rounded-full" />
83+
84+ < button
85+ onClick = { toggleTheme }
86+ className = "p-2.5 rounded-full text-slate-500 dark:text-gray-400 bg-white/40 dark:bg-gray-800/40 hover:bg-white dark:hover:bg-gray-700 hover:text-blue-600 transition-all shadow-sm ring-1 ring-slate-200/50 dark:ring-transparent"
11787 >
118- Contributors
88+ { mode === "dark" ? < Sun className = "h-5 w-5" /> : < Moon className = "h-5 w-5" /> }
89+ </ button >
90+
91+ < Link to = "/login" className = "text-lg font-bold text-slate-700 dark:text-gray-200 hover:text-blue-600 transition-colors px-2" >
92+ Login
11993 </ Link >
94+
12095 < Link
121- to = "/login"
122- className = "block text-lg font-medium hover:text-gray-300 transition-all px-2 py-1 border border-transparent hover:border-gray-400 rounded"
123- onClick = { ( ) => setIsOpen ( false ) }
96+ to = "/signup"
97+ className = "flex items-center space-x-2 px-7 py-3 text-lg font-bold text-white bg-blue-600 rounded-full hover:bg-blue-700 hover:shadow-[0_0_20px_rgba(37,99,235,0.3)] transition-all active:scale-95"
12498 >
125- Login
99+ < UserPlus className = "h-5 w-5" />
100+ < span > Sign Up</ span >
126101 </ Link >
102+ </ div >
103+
104+ { /* Mobile Toggle */ }
105+ < div className = "lg:hidden flex items-center space-x-3" >
106+ < button onClick = { toggleTheme } className = "p-2 text-slate-500 dark:text-gray-400" >
107+ { mode === "dark" ? < Sun className = "h-6 w-6" /> : < Moon className = "h-6 w-6" /> }
108+ </ button >
127109 < button
128- onClick = { ( ) => {
129- toggleTheme ( ) ;
130- setIsOpen ( false ) ;
131- } }
132- className = "text-sm font-semibold px-3 py-1 rounded border border-gray-500 hover:text-gray-300 hover:border-gray-300 transition duration-200 w-full text-left"
110+ onClick = { ( ) => setIsOpen ( ! isOpen ) }
111+ className = "p-2.5 rounded-2xl bg-white/80 dark:bg-gray-800 text-slate-900 dark:text-white shadow-sm ring-1 ring-slate-200"
133112 >
134- { mode === "dark" ? "🌞 Light" : "🌙 Dark" }
113+ { isOpen ? < X className = "h-7 w-7" /> : < Menu className = "h-7 w-7" /> }
135114 </ button >
136115 </ div >
137116 </ div >
138- ) }
117+ </ div >
118+
119+ { /* Mobile Drawer */ }
120+ < div className = { `lg:hidden overflow-hidden transition-all duration-500 ease-in-out bg-white/95 dark:bg-gray-900 ${ isOpen ? "max-h-[600px] opacity-100 border-t border-indigo-50" : "max-h-0 opacity-0" } ` } >
121+ < div className = "px-5 py-10 space-y-4" >
122+ < MobileNavLink to = "/" onClick = { ( ) => setIsOpen ( false ) } > Home</ MobileNavLink >
123+
124+ { /* Mobile Features Link */ }
125+ < button
126+ onClick = { scrollToFeatures }
127+ className = "block w-full text-left px-6 py-4 rounded-2xl text-xl font-bold text-slate-600 dark:text-gray-400 hover:bg-indigo-50 dark:hover:bg-gray-800 transition-all"
128+ >
129+ Features
130+ </ button >
131+
132+ < MobileNavLink to = "/track" onClick = { ( ) => setIsOpen ( false ) } > Tracker</ MobileNavLink >
133+ < MobileNavLink to = "/contributors" onClick = { ( ) => setIsOpen ( false ) } > Contributors</ MobileNavLink >
134+
135+ < div className = "pt-8 mt-6 border-t border-slate-100 grid grid-cols-2 gap-5" >
136+ < Link to = "/login" className = "flex items-center justify-center py-4 text-lg font-bold text-slate-700 bg-slate-50 rounded-2xl" onClick = { ( ) => setIsOpen ( false ) } >
137+ Login
138+ </ Link >
139+ < Link to = "/signup" className = "flex items-center justify-center py-4 text-lg font-bold text-white bg-blue-600 rounded-2xl shadow-lg" onClick = { ( ) => setIsOpen ( false ) } >
140+ Sign Up
141+ </ Link >
142+ </ div >
143+ </ div >
144+ </ div >
139145 </ nav >
140146 ) ;
141147} ;
142148
143- export default Navbar ;
149+ const MobileNavLink = ( { to, children, onClick } : { to : string , children : React . ReactNode , onClick : ( ) => void } ) => (
150+ < NavLink
151+ to = { to }
152+ onClick = { onClick }
153+ className = { ( { isActive } ) =>
154+ `block px-6 py-4 rounded-2xl text-xl font-bold transition-all ${
155+ isActive ? "bg-blue-600 text-white shadow-lg" : "text-slate-600 dark:text-gray-400 hover:bg-indigo-50 dark:hover:bg-gray-800"
156+ } `
157+ }
158+ >
159+ { children }
160+ </ NavLink >
161+ ) ;
162+
163+ export default Navbar ;
0 commit comments