Skip to content

Commit e689afa

Browse files
Improve Navbar UI/UX of the Website
1 parent 56e17a3 commit e689afa

1 file changed

Lines changed: 136 additions & 116 deletions

File tree

src/components/Navbar.tsx

Lines changed: 136 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -1,143 +1,163 @@
1-
import { Link } from "react-router-dom";
1+
import { NavLink, Link, useLocation, useNavigate } from "react-router-dom";
22
import { useState, useContext } from "react";
33
import { ThemeContext } from "../context/ThemeContext";
4-
import { Moon, Sun } from 'lucide-react';
5-
4+
import { Moon, Sun, Menu, X, UserPlus } from 'lucide-react';
65

76
const 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

Comments
 (0)