Skip to content

Commit 3cddb29

Browse files
Feat: add hamburger menu
1 parent 06b3c00 commit 3cddb29

File tree

1 file changed

+108
-0
lines changed

1 file changed

+108
-0
lines changed

src/components/Header.tsx

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ const baseLinks = [
2424
const Header: React.FC<HeaderProps> = ({ fontLoaded, smallLogo }) => {
2525
const location = useLocation();
2626
const [openMenuId, setOpenMenuId] = React.useState<string | null>(null);
27+
const [isMobileMenuOpen, setIsMobileMenuOpen] = React.useState(false);
2728

2829
React.useEffect(() => {
2930
const handleClickOutside = (event: MouseEvent) => {
@@ -42,6 +43,11 @@ const Header: React.FC<HeaderProps> = ({ fontLoaded, smallLogo }) => {
4243
setOpenMenuId(openMenuId === menuId ? null : menuId);
4344
};
4445

46+
const toggleMobileMenu = () => {
47+
setIsMobileMenuOpen(!isMobileMenuOpen);
48+
setOpenMenuId(null);
49+
}
50+
4551
const getFilteredChildren = (children: Array<{ name: string; path: string }>) => {
4652
return children.filter(child => child.path !== location.pathname);
4753
}
@@ -76,6 +82,38 @@ const Header: React.FC<HeaderProps> = ({ fontLoaded, smallLogo }) => {
7682
py versify
7783
</span>
7884
</div>
85+
86+
{/* Hamburger Menu Button */}
87+
<button
88+
className="md:hidden p-2 rounded-lg hover:bg-[#3a719b] transition-colors"
89+
onClick={toggleMobileMenu}
90+
aria-label="Toggle menu"
91+
>
92+
<svg
93+
className="w-6 h-6"
94+
fill="none"
95+
stroke="currentColor"
96+
viewBox="0 0 24 24"
97+
>
98+
{isMobileMenuOpen ? (
99+
<path
100+
strokeLinecap="round"
101+
strokeLinejoin="round"
102+
strokeWidth={2}
103+
d="M6 18L18 6M6 6l12 12"
104+
/>
105+
) : (
106+
<path
107+
strokeLinecap="round"
108+
strokeLinejoin="round"
109+
strokeWidth={2}
110+
d="M4 6h16M4 12h16M4 18h16"
111+
/>
112+
)}
113+
</svg>
114+
</button>
115+
116+
{/* Regular Menu */}
79117
<div className="hidden md:flex space-x-8">
80118
{headerLinks.map((link, index) => (
81119
link.children ? (
@@ -144,6 +182,76 @@ const Header: React.FC<HeaderProps> = ({ fontLoaded, smallLogo }) => {
144182
)
145183
))}
146184
</div>
185+
186+
{/* Mobile Menu */}
187+
<div
188+
className={`${
189+
isMobileMenuOpen ? 'block' : 'hidden'
190+
} absolute top-full left-0 right-0 bg-[#4584b6] md:hidden shadow-lg`}
191+
>
192+
<div className="px-4 py-2">
193+
{location.pathname !== '/' && (
194+
<Link
195+
to="/"
196+
className="block py-2 px-4 text-white hover:text-[#ffde57] transition-colors"
197+
onClick={() => setIsMobileMenuOpen(false)}
198+
>
199+
Home
200+
</Link>
201+
)}
202+
{baseLinks.map((link, index) => (
203+
<div key={index}>
204+
{link.children ? (
205+
<div className="relative">
206+
<button
207+
onClick={(e) => handleMenuClick(link.name, e)}
208+
className="w-full flex items-center justify-between py-2 px-4 text-white hover:text-[#ffde57] transition-colors"
209+
>
210+
{link.name}
211+
<svg
212+
className={`w-4 h-4 transform transition-transform ${
213+
openMenuId === link.name ? 'rotate-180' : ''
214+
}`}
215+
fill="none"
216+
stroke="currentColor"
217+
viewBox="0 0 24 24"
218+
>
219+
<path
220+
strokeLinecap="round"
221+
strokeLinejoin="round"
222+
strokeWidth={2}
223+
d="M19 9l-7 7-7-7"
224+
/>
225+
</svg>
226+
</button>
227+
{openMenuId === link.name && (
228+
<div className="bg-[#3a719b] py-1">
229+
{link.children.map((child, childIndex) => (
230+
<Link
231+
key={childIndex}
232+
to={child.path}
233+
className="block py-2 px-8 text-white hover:text-[#ffde57] transition-colors"
234+
onClick={() => setIsMobileMenuOpen(false)}
235+
>
236+
{child.name}
237+
</Link>
238+
))}
239+
</div>
240+
)}
241+
</div>
242+
) : (
243+
<a
244+
href={link.path}
245+
className="block py-2 px-4 text-white hover:text-[#ffde57] transition-colors"
246+
onClick={() => setIsMobileMenuOpen(false)}
247+
>
248+
{link.name}
249+
</a>
250+
)}
251+
</div>
252+
))}
253+
</div>
254+
</div>
147255
</nav>
148256
</div>
149257
</header>

0 commit comments

Comments
 (0)