Redesign sidebar nav and stretch Glance layout to fill viewport

Sidebar: prominent gold arc logo using a cleaned transparent-background
asset (keys out the source PNG's baked-in brown texture), horizontal
icon+label nav items with larger spacing, and a filled gold-tinted
highlight box on the selected item.

Layout: main content is now a flex column filling the viewport - hero
fixed at top, middle row (Resource Overview / Recent Activity / Top
Alerts) stretches to fill available height with items distributed, and
the bottom row (Network Traffic / Shortcuts) anchored to the bottom.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BbJV5nm8KPVH1oNJYKpnoF
This commit is contained in:
Claude 2026-06-18 14:53:34 +00:00
parent 40bd0c9ec7
commit 1cbc1dab40
No known key found for this signature in database
4 changed files with 48 additions and 46 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 MiB

View file

@ -23,12 +23,11 @@ function App() {
<TopBar /> <TopBar />
<section <section
className="w-full overflow-y-auto" className="flex w-full flex-col overflow-hidden"
style={{ height: 'calc(100vh - 56px)', scrollbarWidth: 'none', padding: '16px 24px 32px 24px' }} style={{ height: 'calc(100vh - 56px)', scrollbarWidth: 'none', padding: '16px 24px 24px 24px', gap: '20px' }}
> >
<div className="flex w-full max-w-none flex-col gap-0"> {/* Hero + KPI overlap — KPI bottom aligns with banner bottom */}
{/* Hero + KPI overlap — KPI bottom aligns with banner bottom */} <div className="relative w-full shrink-0 overflow-hidden" style={{ height: '240px' }}>
<div className="relative w-full overflow-hidden" style={{ height: '260px' }}>
<img <img
src="/archnest-hero-banner.png" src="/archnest-hero-banner.png"
alt="ArchNest Banner" alt="ArchNest Banner"
@ -53,22 +52,19 @@ function App() {
'radial-gradient(ellipse 75% 100% at center, transparent 55%, var(--color-page) 100%)', 'radial-gradient(ellipse 75% 100% at center, transparent 55%, var(--color-page) 100%)',
}} }}
/> />
{/* KPI cards positioned so their bottom edge aligns with banner bottom */} {/* KPI cards positioned so their bottom edge aligns with banner bottom */}
<div className="absolute bottom-0 left-0 right-0 z-10 px-4"> <div className="absolute bottom-0 left-0 right-0 z-10 px-4">
<StatusCards /> <StatusCards />
</div>
</div> </div>
</div>
{/* 24px breathing room between KPI row and middle row */} {/* Middle Row — stretches to fill available vertical space */}
<div style={{ height: '24px' }} /> <div className="min-h-0 flex-1">
{/* Middle Row */}
<MiddleRow /> <MiddleRow />
</div>
{/* Gap */} {/* Bottom Row — anchored to the bottom */}
<div style={{ height: '24px' }} /> <div className="shrink-0">
{/* Bottom Row */}
<BottomRow /> <BottomRow />
</div> </div>
</section> </section>

View file

@ -32,6 +32,9 @@ const cardBase: React.CSSProperties = {
transition: 'border-color 0.2s ease', transition: 'border-color 0.2s ease',
position: 'relative', position: 'relative',
overflow: 'hidden', overflow: 'hidden',
height: '100%',
display: 'flex',
flexDirection: 'column',
} }
function getBarColor(percentage: number) { function getBarColor(percentage: number) {
@ -42,7 +45,7 @@ function getBarColor(percentage: number) {
export default function MiddleRow() { export default function MiddleRow() {
return ( return (
<div className="grid w-full grid-cols-[1fr_1.4fr_1fr] gap-6"> <div className="grid h-full w-full grid-cols-[1fr_1.4fr_1fr] gap-6">
{/* Resource Overview */} {/* Resource Overview */}
<div style={cardBase} className="hover:!border-gold/15 group"> <div style={cardBase} className="hover:!border-gold/15 group">
{/* Subtle hex pattern overlay */} {/* Subtle hex pattern overlay */}
@ -50,7 +53,7 @@ export default function MiddleRow() {
{/* Gold top edge lighting */} {/* Gold top edge lighting */}
<div style={{ position: 'absolute', top: 0, left: '10%', right: '10%', height: '1px', background: 'linear-gradient(90deg, transparent, rgba(200,164,52,0.15), transparent)', pointerEvents: 'none' }} /> <div style={{ position: 'absolute', top: 0, left: '10%', right: '10%', height: '1px', background: 'linear-gradient(90deg, transparent, rgba(200,164,52,0.15), transparent)', pointerEvents: 'none' }} />
<div className="relative z-10"> <div className="relative z-10 flex flex-1 flex-col">
<div className="flex items-center justify-between mb-4"> <div className="flex items-center justify-between mb-4">
<h3 style={{ fontSize: '11px', textTransform: 'uppercase', letterSpacing: '1.5px', color: '#7A7D85', fontWeight: 500 }}> <h3 style={{ fontSize: '11px', textTransform: 'uppercase', letterSpacing: '1.5px', color: '#7A7D85', fontWeight: 500 }}>
Resource Overview Resource Overview
@ -59,7 +62,7 @@ export default function MiddleRow() {
<X size={14} /> <X size={14} />
</button> </button>
</div> </div>
<div className="flex flex-col gap-4"> <div className="flex flex-1 flex-col justify-around gap-4">
{resources.map((res) => { {resources.map((res) => {
const percentage = res.unit === '%' ? res.current : (res.current / res.max) * 100 const percentage = res.unit === '%' ? res.current : (res.current / res.max) * 100
const displayValue = res.unit === '%' ? `${res.current}%` : `${res.current} / ${res.max}${res.unit}` const displayValue = res.unit === '%' ? `${res.current}%` : `${res.current} / ${res.max}${res.unit}`
@ -84,7 +87,7 @@ export default function MiddleRow() {
{/* Gold top edge */} {/* Gold top edge */}
<div style={{ position: 'absolute', top: 0, left: '5%', right: '5%', height: '1px', background: 'linear-gradient(90deg, transparent, rgba(200,164,52,0.2), transparent)', pointerEvents: 'none' }} /> <div style={{ position: 'absolute', top: 0, left: '5%', right: '5%', height: '1px', background: 'linear-gradient(90deg, transparent, rgba(200,164,52,0.2), transparent)', pointerEvents: 'none' }} />
<div className="relative z-10"> <div className="relative z-10 flex flex-1 flex-col">
<div className="flex items-center justify-between mb-4"> <div className="flex items-center justify-between mb-4">
<h3 style={{ fontSize: '11px', textTransform: 'uppercase', letterSpacing: '1.5px', color: '#7A7D85', fontWeight: 500 }}> <h3 style={{ fontSize: '11px', textTransform: 'uppercase', letterSpacing: '1.5px', color: '#7A7D85', fontWeight: 500 }}>
Recent Activity Recent Activity
@ -93,7 +96,7 @@ export default function MiddleRow() {
<X size={14} /> <X size={14} />
</button> </button>
</div> </div>
<div className="flex flex-col gap-3"> <div className="flex flex-1 flex-col justify-around gap-3">
{activities.map((item, i) => { {activities.map((item, i) => {
const Icon = item.icon const Icon = item.icon
return ( return (
@ -118,14 +121,14 @@ export default function MiddleRow() {
{/* Amber edge lighting */} {/* Amber edge lighting */}
<div style={{ position: 'absolute', top: 0, left: '10%', right: '10%', height: '1px', background: 'linear-gradient(90deg, transparent, rgba(231,126,34,0.15), transparent)', pointerEvents: 'none' }} /> <div style={{ position: 'absolute', top: 0, left: '10%', right: '10%', height: '1px', background: 'linear-gradient(90deg, transparent, rgba(231,126,34,0.15), transparent)', pointerEvents: 'none' }} />
<div className="relative z-10"> <div className="relative z-10 flex flex-1 flex-col">
<div className="flex items-center justify-between mb-4"> <div className="flex items-center justify-between mb-4">
<h3 style={{ fontSize: '11px', textTransform: 'uppercase', letterSpacing: '1.5px', color: '#7A7D85', fontWeight: 500 }}> <h3 style={{ fontSize: '11px', textTransform: 'uppercase', letterSpacing: '1.5px', color: '#7A7D85', fontWeight: 500 }}>
Top Alerts Top Alerts
</h3> </h3>
<a href="#" style={{ fontSize: '11px', color: '#C8A434', textDecoration: 'none' }}>View all</a> <a href="#" style={{ fontSize: '11px', color: '#C8A434', textDecoration: 'none' }}>View all</a>
</div> </div>
<div className="flex flex-col gap-3"> <div className="flex flex-1 flex-col justify-around gap-3">
{alerts.map((alert, i) => ( {alerts.map((alert, i) => (
<div key={i} className="flex items-start gap-3"> <div key={i} className="flex items-start gap-3">
<div style={{ width: '8px', height: '8px', borderRadius: '50%', flexShrink: 0, marginTop: '5px', backgroundColor: alert.severity === 'high' ? '#E74C3C' : '#E67E22', boxShadow: alert.severity === 'high' ? '0 0 6px rgba(231,76,60,0.3)' : '0 0 6px rgba(230,126,34,0.2)' }} /> <div style={{ width: '8px', height: '8px', borderRadius: '50%', flexShrink: 0, marginTop: '5px', backgroundColor: alert.severity === 'high' ? '#E74C3C' : '#E67E22', boxShadow: alert.severity === 'high' ? '0 0 6px rgba(231,76,60,0.3)' : '0 0 6px rgba(230,126,34,0.2)' }} />

View file

@ -28,51 +28,54 @@ export default function Sidebar({ collapsed, onToggle }: SidebarProps) {
return ( return (
<aside <aside
className="fixed left-0 top-0 z-50 h-screen overflow-hidden flex flex-col items-center py-5" className="fixed left-0 top-0 z-50 h-screen overflow-hidden flex flex-col py-6"
style={{ width: `${width}px`, backgroundColor: '#0A0B0D' }} style={{ width: `${width}px`, backgroundColor: '#0A0B0D' }}
> >
{/* Logo — larger, aligned with top bar */} {/* Logo prominent, centered at top. Blend mode hides the baked-in
<div className="flex flex-col items-center mb-6" style={{ paddingTop: '8px' }}> dark background of the source PNG so only the gold arc shows. */}
<div className="flex flex-col items-center mb-10" style={{ paddingTop: '4px' }}>
<img <img
src="/archnest-logo.png" src="/archnest-logo-clean.png"
alt="ArchNest" alt="ArchNest"
className="mb-1.5"
style={{ style={{
width: collapsed ? '28px' : '44px', width: collapsed ? '56px' : '168px',
height: collapsed ? '28px' : '44px', height: 'auto',
filter: 'drop-shadow(0 0 8px rgba(200,164,52,0.5))', filter: 'drop-shadow(0 0 10px rgba(200,164,52,0.3))',
}} }}
/> />
{!collapsed && (
<span style={{ fontSize: '9px', fontWeight: 700, letterSpacing: '2.5px', color: '#C8A434', textTransform: 'uppercase' }}>
ArchNest
</span>
)}
</div> </div>
{/* Nav Items */} {/* Nav Items */}
<nav className="flex-1 flex flex-col justify-center gap-6 w-full"> <nav className="flex-1 flex flex-col gap-2 w-full" style={{ padding: collapsed ? '0 8px' : '0 12px' }}>
{navItems.map((item) => { {navItems.map((item) => {
const Icon = item.icon const Icon = item.icon
return ( return (
<a <a
key={item.label} key={item.label}
href={item.route} href={item.route}
className="relative flex w-full flex-col items-center justify-center gap-1.5 px-2 py-2 text-center no-underline transition-all duration-200" className={`relative flex items-center no-underline transition-all duration-200 ${collapsed ? 'justify-center' : ''}`}
style={{ color: item.active ? '#C8A434' : '#7A7D85' }} style={{
color: item.active ? '#C8A434' : '#7A7D85',
gap: collapsed ? '0' : '12px',
padding: collapsed ? '12px 0' : '12px 14px',
borderRadius: '10px',
backgroundColor: item.active ? 'rgba(200,164,52,0.1)' : 'transparent',
border: item.active ? '1px solid rgba(200,164,52,0.18)' : '1px solid transparent',
boxShadow: item.active ? '0 0 14px rgba(200,164,52,0.06)' : 'none',
}}
title={collapsed ? item.label : undefined} title={collapsed ? item.label : undefined}
onMouseEnter={(e) => { if (!item.active) e.currentTarget.style.backgroundColor = 'rgba(200,164,52,0.05)'; e.currentTarget.style.color = '#C8A434' }} onMouseEnter={(e) => { if (!item.active) { e.currentTarget.style.backgroundColor = 'rgba(200,164,52,0.05)'; e.currentTarget.style.color = '#C8A434' } }}
onMouseLeave={(e) => { e.currentTarget.style.backgroundColor = 'transparent'; if (!item.active) e.currentTarget.style.color = '#7A7D85' }} onMouseLeave={(e) => { if (!item.active) { e.currentTarget.style.backgroundColor = 'transparent'; e.currentTarget.style.color = '#7A7D85' } }}
> >
{item.active && ( {item.active && (
<div <div
className="absolute left-0 top-1/2 -translate-y-1/2 rounded-r" className="absolute left-0 top-1/2 -translate-y-1/2"
style={{ width: '3px', height: '26px', backgroundColor: '#C8A434', boxShadow: '0 0 6px rgba(200,164,52,0.5)' }} style={{ width: '3px', height: '22px', backgroundColor: '#C8A434', borderRadius: '0 3px 3px 0', boxShadow: '0 0 6px rgba(200,164,52,0.5)' }}
/> />
)} )}
<Icon className="h-5 w-5 shrink-0" strokeWidth={item.active ? 2 : 1.5} /> <Icon className="h-5 w-5 shrink-0" strokeWidth={item.active ? 2 : 1.5} />
{!collapsed && ( {!collapsed && (
<span className="max-w-[90px] truncate leading-tight font-medium" style={{ fontSize: '10px' }}> <span className="truncate leading-tight font-medium" style={{ fontSize: '13px' }}>
{item.label} {item.label}
</span> </span>
)} )}
@ -84,7 +87,7 @@ export default function Sidebar({ collapsed, onToggle }: SidebarProps) {
{/* Collapse Toggle */} {/* Collapse Toggle */}
<button <button
onClick={onToggle} onClick={onToggle}
className="p-1.5 rounded cursor-pointer bg-transparent transition-colors" className="p-1.5 rounded cursor-pointer bg-transparent transition-colors self-center"
style={{ border: '1px solid #1E2025', color: '#7A7D85', marginBottom: '12px' }} style={{ border: '1px solid #1E2025', color: '#7A7D85', marginBottom: '12px' }}
> >
{collapsed ? <ChevronRight size={12} /> : <ChevronLeft size={12} />} {collapsed ? <ChevronRight size={12} /> : <ChevronLeft size={12} />}