refactor: implement icon rail sidebar for Design System v4

72px icon rail with hover flyouts, pin-to-expand toggle (260px),
keyboard accessible, mobile hamburger overlay. Flat TopBar styling
(no blur/glass). New BrandLogo mark (gradient square + lightning bolt).
BrandWordmark uses solid text color instead of gradient.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Michael Chihlas
2026-03-22 00:26:19 -04:00
parent 0499284679
commit 8efc443949
7 changed files with 477 additions and 237 deletions

View File

@@ -35,7 +35,7 @@ export function TopBar() {
return () => document.removeEventListener('mousedown', handleClickOutside)
}, [userMenuOpen])
// K / Ctrl+K global shortcut
// Cmd+K / Ctrl+K global shortcut
const handleGlobalKeyDown = useCallback((e: KeyboardEvent) => {
if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
e.preventDefault()
@@ -55,12 +55,10 @@ export function TopBar() {
return (
<>
<header
className="topbar relative z-10 flex items-center gap-4 border-b px-4"
className="topbar relative z-10 flex items-center gap-4 px-4"
style={{
background: 'rgba(16, 17, 20, 0.6)',
backdropFilter: 'var(--glass-blur-strong)',
WebkitBackdropFilter: 'var(--glass-blur-strong)',
borderColor: 'var(--glass-border)',
background: '#0f1118',
borderBottom: '1px solid #1e2130',
}}
>
{/* Logo area */}
@@ -68,10 +66,9 @@ export function TopBar() {
to="/"
className="flex items-center gap-2.5 pr-4 transition-all duration-200"
>
<BrandLogo size="sm" className="h-7 w-7 shrink-0" />
<span className="text-sm font-heading font-bold tracking-tight whitespace-nowrap">
<span className="text-foreground">Resolution</span>
<span className="text-gradient-brand">Flow</span>
<BrandLogo size="sm" />
<span className="text-sm font-heading font-bold tracking-tight whitespace-nowrap text-[#f0f2f5]">
ResolutionFlow
</span>
</Link>
@@ -84,17 +81,28 @@ export function TopBar() {
className="hidden sm:relative sm:block w-full text-left"
style={{ maxWidth: '480px' }}
>
<Search size={16} className="absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground" />
<div className="w-full rounded-lg border border-border bg-card py-2 pl-9 pr-14 text-[0.8125rem] text-muted-foreground cursor-pointer hover:border-primary/30 transition-colors">
Search flows, sessions, tags
<Search size={16} className="absolute left-3 top-1/2 -translate-y-1/2 text-[#848b9b]" />
<div
className="w-full rounded-md py-2 pl-9 pr-14 text-[0.8125rem] text-[#848b9b] cursor-pointer transition-colors"
style={{
background: '#14161d',
border: '1px solid #1e2130',
}}
onMouseEnter={(e) => { (e.currentTarget as HTMLElement).style.borderColor = '#2a2f3d' }}
onMouseLeave={(e) => { (e.currentTarget as HTMLElement).style.borderColor = '#1e2130' }}
>
Search flows, sessions, tags...
</div>
<span className="absolute right-3 top-1/2 -translate-y-1/2 rounded border border-border bg-background px-1.5 py-0.5 font-label text-[0.625rem] text-muted-foreground">
{navigator.platform?.toLowerCase().includes('mac') ? '⌘K' : 'Ctrl+K'}
<span
className="absolute right-3 top-1/2 -translate-y-1/2 rounded px-1.5 py-0.5 font-mono text-[0.625rem] text-[#4f5666]"
style={{ background: '#0c0d10', border: '1px solid #1e2130' }}
>
{navigator.platform?.toLowerCase().includes('mac') ? '\u2318K' : 'Ctrl+K'}
</span>
</button>
<button
onClick={() => setCommandPaletteOpen(true)}
className="sm:hidden rounded-lg p-2 text-muted-foreground hover:bg-card hover:text-foreground transition-colors"
className="sm:hidden rounded-lg p-2 text-[#848b9b] hover:text-[#e2e5eb] transition-colors"
title="Search"
>
<Search size={18} />
@@ -107,14 +115,14 @@ export function TopBar() {
<div className="flex items-center gap-1">
<button
onClick={() => setQuickLaunchOpen(true)}
className="rounded-lg p-2 text-muted-foreground hover:bg-card hover:text-foreground transition-colors"
className="rounded-lg p-2 text-[#848b9b] hover:bg-[#14161d] hover:text-[#e2e5eb] transition-colors"
title="Quick Launch"
>
<Zap size={18} />
</button>
<Link
to="/guides"
className="rounded-lg p-2 text-muted-foreground hover:bg-card hover:text-foreground transition-colors"
className="rounded-lg p-2 text-[#848b9b] hover:bg-[#14161d] hover:text-[#e2e5eb] transition-colors"
title="User Guides"
>
<HelpCircle size={18} />
@@ -125,18 +133,22 @@ export function TopBar() {
<div className="relative ml-2" ref={menuRef}>
<button
onClick={() => setUserMenuOpen(!userMenuOpen)}
className="flex h-8 w-8 items-center justify-center rounded-[10px] bg-gradient-brand text-xs font-heading font-bold text-primary-foreground hover:opacity-90 transition-opacity"
className="flex h-8 w-8 items-center justify-center rounded-[10px] text-xs font-heading font-bold text-white hover:opacity-90 transition-opacity"
style={{ background: 'linear-gradient(135deg, #06b6d4, #22d3ee)' }}
title={user?.name || user?.email || 'User'}
>
{initials}
</button>
{userMenuOpen && (
<div className="absolute right-0 z-50 mt-2 w-56 rounded-lg border border-border bg-card p-1 shadow-xl animate-scale-in">
<div className="border-b border-border px-3 py-2.5 mb-1">
<p className="text-sm font-medium text-foreground truncate">{user?.name || user?.email}</p>
<div
className="absolute right-0 z-50 mt-2 w-56 rounded-lg p-1 shadow-xl animate-scale-in"
style={{ background: '#14161d', border: '1px solid #1e2130' }}
>
<div className="px-3 py-2.5 mb-1" style={{ borderBottom: '1px solid #1e2130' }}>
<p className="text-sm font-medium text-[#e2e5eb] truncate">{user?.name || user?.email}</p>
{effectiveRole && effectiveRole !== 'engineer' && (
<span className="mt-1 inline-flex items-center gap-1 text-xs text-muted-foreground">
<span className="mt-1 inline-flex items-center gap-1 text-xs text-[#848b9b]">
<Shield size={10} />
{effectiveRole === 'super_admin' ? 'Super Admin' : effectiveRole === 'owner' ? 'Owner' : 'Viewer'}
</span>
@@ -145,7 +157,7 @@ export function TopBar() {
<Link
to="/account"
onClick={() => setUserMenuOpen(false)}
className="flex items-center gap-2 rounded-md px-3 py-2 text-sm text-muted-foreground hover:bg-accent hover:text-foreground"
className="flex items-center gap-2 rounded-md px-3 py-2 text-sm text-[#848b9b] hover:bg-[#191c25] hover:text-[#e2e5eb]"
>
<Settings size={14} />
Account
@@ -154,18 +166,18 @@ export function TopBar() {
<Link
to="/admin"
onClick={() => setUserMenuOpen(false)}
className="flex items-center gap-2 rounded-md px-3 py-2 text-sm text-muted-foreground hover:bg-accent hover:text-foreground"
className="flex items-center gap-2 rounded-md px-3 py-2 text-sm text-[#848b9b] hover:bg-[#191c25] hover:text-[#e2e5eb]"
>
<Shield size={14} />
Admin Panel
</Link>
)}
<div className="border-t border-border mt-1 pt-1">
<div className="mt-1 pt-1" style={{ borderTop: '1px solid #1e2130' }}>
<button
onClick={handleLogout}
className={cn(
'flex w-full items-center gap-2 rounded-md px-3 py-2 text-sm',
'text-muted-foreground hover:bg-accent hover:text-foreground'
'text-[#848b9b] hover:bg-[#191c25] hover:text-[#e2e5eb]'
)}
>
<LogOut size={14} />