WinslowFan Claude Opus 4.8 commited on
Commit
a4bdc89
·
1 Parent(s): d87c1fb

Collapse header nav into a hamburger menu on mobile

Browse files

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

frontend/src/components/layout/Header.tsx CHANGED
@@ -1,8 +1,20 @@
1
- import { BookOpen, Database, Download } from 'lucide-react';
 
2
  import { Link, useLocation } from 'react-router-dom';
3
 
4
  export function Header() {
5
  const location = useLocation();
 
 
 
 
 
 
 
 
 
 
 
6
 
7
  return (
8
  <header className="border-b border-gray-200 bg-white sticky top-0 z-50 shadow-sm">
@@ -17,34 +29,58 @@ export function Header() {
17
  </div>
18
  </Link>
19
 
20
- <nav className="flex items-center gap-1 sm:gap-2 shrink-0">
21
- <Link
22
- to="/"
23
- className={`flex items-center gap-1.5 px-2.5 sm:px-3 py-2 text-sm rounded-lg transition-colors ${
24
- location.pathname === '/' ? 'bg-slate-100 text-slate-900 font-semibold' : 'text-slate-600 hover:bg-slate-50'
25
- }`}
26
- >
27
  <Database className="w-4 h-4 shrink-0" />
28
- <span className="hidden sm:inline">Explorer</span>
29
  </Link>
30
- <Link
31
- to="/docs"
32
- className={`flex items-center gap-1.5 px-2.5 sm:px-3 py-2 text-sm rounded-lg transition-colors ${
33
- location.pathname === '/docs' ? 'bg-slate-100 text-slate-900 font-semibold' : 'text-slate-600 hover:bg-slate-50'
34
- }`}
35
- >
36
  <BookOpen className="w-4 h-4 shrink-0" />
37
- <span className="hidden sm:inline">Docs</span>
38
  </Link>
39
  <a
40
  href="/api/protein/download/db"
41
- className="flex items-center gap-1.5 px-3 sm:px-4 py-2 text-sm font-medium text-white bg-slate-900 rounded-lg hover:bg-slate-700 transition-colors"
42
  >
43
  <Download className="w-4 h-4 shrink-0" />
44
- <span className="hidden sm:inline">Download DB</span>
45
  </a>
46
  </nav>
 
 
 
 
 
 
 
 
 
 
 
47
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
  </header>
49
  );
50
  }
 
1
+ import { useEffect, useState } from 'react';
2
+ import { BookOpen, Database, Download, Menu, X } from 'lucide-react';
3
  import { Link, useLocation } from 'react-router-dom';
4
 
5
  export function Header() {
6
  const location = useLocation();
7
+ const [menuOpen, setMenuOpen] = useState(false);
8
+
9
+ // Close the mobile menu whenever the route changes
10
+ useEffect(() => {
11
+ setMenuOpen(false);
12
+ }, [location.pathname]);
13
+
14
+ const navItemClass = (active: boolean) =>
15
+ `flex items-center gap-1.5 px-3 py-2 text-sm rounded-lg transition-colors ${
16
+ active ? 'bg-slate-100 text-slate-900 font-semibold' : 'text-slate-600 hover:bg-slate-50'
17
+ }`;
18
 
19
  return (
20
  <header className="border-b border-gray-200 bg-white sticky top-0 z-50 shadow-sm">
 
29
  </div>
30
  </Link>
31
 
32
+ {/* Desktop nav */}
33
+ <nav className="hidden sm:flex items-center gap-2">
34
+ <Link to="/" className={navItemClass(location.pathname === '/')}>
 
 
 
 
35
  <Database className="w-4 h-4 shrink-0" />
36
+ Explorer
37
  </Link>
38
+ <Link to="/docs" className={navItemClass(location.pathname === '/docs')}>
 
 
 
 
 
39
  <BookOpen className="w-4 h-4 shrink-0" />
40
+ Docs
41
  </Link>
42
  <a
43
  href="/api/protein/download/db"
44
+ className="flex items-center gap-1.5 px-4 py-2 text-sm font-medium text-white bg-slate-900 rounded-lg hover:bg-slate-700 transition-colors"
45
  >
46
  <Download className="w-4 h-4 shrink-0" />
47
+ Download DB
48
  </a>
49
  </nav>
50
+
51
+ {/* Mobile menu toggle */}
52
+ <button
53
+ type="button"
54
+ aria-label="Toggle navigation menu"
55
+ aria-expanded={menuOpen}
56
+ onClick={() => setMenuOpen((open) => !open)}
57
+ className="sm:hidden inline-flex items-center justify-center p-2 rounded-lg text-slate-700 hover:bg-slate-100 transition-colors shrink-0"
58
+ >
59
+ {menuOpen ? <X className="w-6 h-6" /> : <Menu className="w-6 h-6" />}
60
+ </button>
61
  </div>
62
+
63
+ {/* Mobile dropdown menu */}
64
+ {menuOpen && (
65
+ <nav className="sm:hidden border-t border-gray-200 bg-white px-4 py-3 flex flex-col gap-1">
66
+ <Link to="/" className={navItemClass(location.pathname === '/')}>
67
+ <Database className="w-4 h-4 shrink-0" />
68
+ Explorer
69
+ </Link>
70
+ <Link to="/docs" className={navItemClass(location.pathname === '/docs')}>
71
+ <BookOpen className="w-4 h-4 shrink-0" />
72
+ Docs
73
+ </Link>
74
+ <a
75
+ href="/api/protein/download/db"
76
+ onClick={() => setMenuOpen(false)}
77
+ className="flex items-center gap-1.5 px-3 py-2 text-sm font-medium text-white bg-slate-900 rounded-lg hover:bg-slate-700 transition-colors"
78
+ >
79
+ <Download className="w-4 h-4 shrink-0" />
80
+ Download DB
81
+ </a>
82
+ </nav>
83
+ )}
84
  </header>
85
  );
86
  }