Skip to content

Commit 65d305f

Browse files
authored
PATCH header layout components structure (#50)
1 parent 5f7fd9b commit 65d305f

1 file changed

Lines changed: 82 additions & 72 deletions

File tree

frontend/src/components/common/LayoutHeader.client.tsx

Lines changed: 82 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -56,85 +56,108 @@ export function LayoutHeader() {
5656
<>
5757
<header className="fixed top-0 left-0 right-0 z-50 bg-surface-950/80 backdrop-blur-sm border-b border-white/5">
5858
<div className="max-w-5xl mx-auto px-3 sm:px-6 py-2.5 sm:py-3">
59-
<div className="flex items-center justify-between gap-2">
60-
<Link href="/" className="flex items-center gap-2 sm:gap-2.5 group min-w-0">
61-
<span className="text-lg sm:text-xl flex-shrink-0">🍜</span>
62-
<span className="font-semibold text-white group-hover:text-amber-100 transition-colors text-sm sm:text-base truncate">Protocol Soup</span>
63-
</Link>
59+
<div className="flex items-center gap-2">
60+
<div className="flex-1 flex items-center">
61+
<Link href="/" className="flex items-center gap-2 sm:gap-2.5 group flex-shrink-0">
62+
<span className="text-lg sm:text-xl flex-shrink-0">🍜</span>
63+
<span className="font-semibold text-white group-hover:text-amber-100 transition-colors text-sm sm:text-base whitespace-nowrap">Protocol Soup</span>
64+
</Link>
65+
</div>
6466

65-
<nav className="hidden lg:flex items-center gap-1">
66-
{showSearchChip && (
67-
<button
68-
type="button"
69-
onClick={openPalette}
70-
aria-haspopup="dialog"
71-
aria-label="Open search palette"
72-
className="flex items-center gap-2 px-3 py-1.5 rounded-md transition-colors text-sm text-surface-400 hover:text-white hover:bg-white/5 mr-1"
73-
>
74-
<Search className="w-4 h-4" />
75-
<span>Search</span>
76-
{shortcutLabel && (
77-
<kbd className="ml-1 hidden xl:inline-flex items-center rounded border border-white/10 bg-surface-800/60 px-1.5 py-0.5 text-[10px] font-mono text-surface-300">
78-
{shortcutLabel}
79-
</kbd>
80-
)}
81-
</button>
82-
)}
67+
<nav className="hidden lg:flex items-center gap-0.5 flex-shrink-0">
8368
{navItems.map((item) => {
8469
const isActive = currentPath === item.path ||
8570
(item.path !== '/' && currentPath.startsWith(item.path))
8671
return (
8772
<Link
8873
key={item.path}
8974
href={item.path}
90-
className={`flex items-center gap-2 px-3 py-1.5 rounded-md transition-colors text-sm ${
75+
aria-current={isActive ? 'page' : undefined}
76+
className={`flex items-center gap-2 px-2.5 py-1.5 rounded-md transition-colors text-sm whitespace-nowrap flex-shrink-0 ${
9177
isActive
9278
? 'bg-white/10 text-white'
9379
: 'text-surface-400 hover:text-white hover:bg-white/5'
9480
}`}
9581
>
96-
<item.icon className="w-4 h-4" />
82+
<item.icon className="w-4 h-4 flex-shrink-0" />
9783
<span>{item.label}</span>
9884
</Link>
9985
)
10086
})}
101-
<div className="w-px h-4 bg-white/10 mx-2" />
102-
<a
103-
href="https://docs.protocolsoup.com"
104-
target="_blank"
105-
rel="noopener noreferrer"
106-
className="flex items-center gap-1.5 px-3 py-1.5 rounded-md text-surface-400 hover:text-white hover:bg-white/5 transition-colors text-sm"
107-
>
108-
<FileText className="w-4 h-4" />
109-
<span>Docs</span>
110-
<ExternalLink className="w-3 h-3" />
111-
</a>
112-
<a
113-
href="https://github.com/ParleSec/ProtocolSoup"
114-
target="_blank"
115-
rel="noopener noreferrer"
116-
className="flex items-center gap-1.5 px-3 py-1.5 rounded-md text-surface-400 hover:text-white hover:bg-white/5 transition-colors text-sm"
117-
>
118-
<Github className="w-4 h-4" />
119-
<span>Source</span>
120-
<ExternalLink className="w-3 h-3" />
121-
</a>
12287
</nav>
12388

124-
<button
125-
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
126-
className="lg:hidden p-2 -mr-2 rounded-lg text-surface-400 hover:text-white hover:bg-white/5 transition-colors"
127-
aria-label={isMobileMenuOpen ? 'Close menu' : 'Open menu'}
128-
aria-haspopup="dialog"
129-
aria-expanded={isMobileMenuOpen}
130-
aria-controls="mobile-nav-drawer"
131-
>
132-
{isMobileMenuOpen ? (
133-
<X className="w-6 h-6" />
134-
) : (
135-
<Menu className="w-6 h-6" />
89+
<div className="flex-1 min-w-0 flex items-center justify-end gap-1">
90+
<div className="hidden lg:flex items-center gap-1 min-w-0">
91+
{showSearchChip && (
92+
<button
93+
type="button"
94+
onClick={openPalette}
95+
aria-haspopup="dialog"
96+
aria-label="Search protocols and docs"
97+
title="Search (press the shortcut to open)"
98+
className="flex items-center justify-center h-9 w-9 rounded-md text-surface-400 hover:text-white hover:bg-white/5 transition-colors flex-shrink-0 xl:w-auto xl:justify-start xl:gap-2 xl:px-3 xl:border xl:border-white/10 xl:bg-surface-900/40 xl:hover:bg-surface-900/70"
99+
>
100+
<Search className="w-4 h-4 flex-shrink-0" />
101+
<span className="hidden xl:inline text-sm">Search</span>
102+
{shortcutLabel && (
103+
<kbd className="hidden 2xl:inline-flex items-center rounded border border-white/10 bg-surface-800/60 px-1.5 py-0.5 text-[10px] font-mono text-surface-300">
104+
{shortcutLabel}
105+
</kbd>
106+
)}
107+
</button>
108+
)}
109+
<div className="w-px h-5 bg-white/10 mx-1 flex-shrink-0" />
110+
<a
111+
href="https://docs.protocolsoup.com"
112+
target="_blank"
113+
rel="noopener noreferrer"
114+
aria-label="Documentation (opens in a new tab)"
115+
title="Documentation"
116+
className="flex items-center justify-center h-9 w-9 rounded-md text-surface-400 hover:text-white hover:bg-white/5 transition-colors flex-shrink-0 xl:w-auto xl:justify-start xl:gap-1.5 xl:px-2.5"
117+
>
118+
<FileText className="w-4 h-4 flex-shrink-0" />
119+
<span className="hidden xl:inline text-sm">Docs</span>
120+
</a>
121+
<a
122+
href="https://github.com/ParleSec/ProtocolSoup"
123+
target="_blank"
124+
rel="noopener noreferrer"
125+
aria-label="Source code on GitHub (opens in a new tab)"
126+
title="Source on GitHub"
127+
className="flex items-center justify-center h-9 w-9 rounded-md text-surface-400 hover:text-white hover:bg-white/5 transition-colors flex-shrink-0 xl:w-auto xl:justify-start xl:gap-1.5 xl:px-2.5"
128+
>
129+
<Github className="w-4 h-4 flex-shrink-0" />
130+
<span className="hidden xl:inline text-sm">Source</span>
131+
</a>
132+
</div>
133+
134+
{/* Mobile controls */}
135+
{showSearchChip && (
136+
<button
137+
type="button"
138+
onClick={openPalette}
139+
className="lg:hidden p-2 rounded-lg text-surface-400 hover:text-white hover:bg-white/5 transition-colors"
140+
aria-haspopup="dialog"
141+
aria-label="Search protocols and docs"
142+
>
143+
<Search className="w-6 h-6" />
144+
</button>
136145
)}
137-
</button>
146+
<button
147+
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
148+
className="lg:hidden p-2 -mr-2 rounded-lg text-surface-400 hover:text-white hover:bg-white/5 transition-colors"
149+
aria-label={isMobileMenuOpen ? 'Close menu' : 'Open menu'}
150+
aria-haspopup="dialog"
151+
aria-expanded={isMobileMenuOpen}
152+
aria-controls="mobile-nav-drawer"
153+
>
154+
{isMobileMenuOpen ? (
155+
<X className="w-6 h-6" />
156+
) : (
157+
<Menu className="w-6 h-6" />
158+
)}
159+
</button>
160+
</div>
138161
</div>
139162
</div>
140163
</header>
@@ -166,19 +189,6 @@ export function LayoutHeader() {
166189
</div>
167190

168191
<div className="flex-1 overflow-y-auto p-4 space-y-1">
169-
{showSearchChip && (
170-
<button
171-
type="button"
172-
onClick={() => {
173-
setIsMobileMenuOpen(false)
174-
openPalette()
175-
}}
176-
className="flex w-full items-center gap-3 px-4 py-3 rounded-xl text-surface-400 hover:text-white hover:bg-white/5 transition-colors"
177-
>
178-
<Search className="w-5 h-5" />
179-
<span className="font-medium">Search</span>
180-
</button>
181-
)}
182192
{navItems.map((item) => {
183193
const isActive = currentPath === item.path ||
184194
(item.path !== '/' && currentPath.startsWith(item.path))

0 commit comments

Comments
 (0)