Sidebar expanded width 140px -> 200px and collapsed 60px -> 64px to match mockup proportions. Hero banner now uses a fixed shorter height with object-fit cover, a bottom mask fade, and a radial vignette so its edges blend into the page background instead of sitting in a bordered box. KPI cards are now semi-transparent so the hero image bleeds through behind them. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BbJV5nm8KPVH1oNJYKpnoF
80 lines
2.9 KiB
TypeScript
80 lines
2.9 KiB
TypeScript
import { useState } from 'react'
|
|
import Sidebar from './components/Sidebar'
|
|
import TopBar from './components/TopBar'
|
|
import StatusCards from './components/StatusCards'
|
|
import MiddleRow from './components/MiddleRow'
|
|
import BottomRow from './components/BottomRow'
|
|
|
|
function App() {
|
|
const [sidebarCollapsed, setSidebarCollapsed] = useState(false)
|
|
const sidebarWidth = sidebarCollapsed ? 64 : 200
|
|
|
|
return (
|
|
<div className="min-h-screen w-screen overflow-hidden bg-page">
|
|
<Sidebar
|
|
collapsed={sidebarCollapsed}
|
|
onToggle={() => setSidebarCollapsed(!sidebarCollapsed)}
|
|
/>
|
|
|
|
<main
|
|
className="h-screen overflow-hidden"
|
|
style={{ marginLeft: `${sidebarWidth}px`, width: `calc(100vw - ${sidebarWidth}px)` }}
|
|
>
|
|
<TopBar />
|
|
|
|
<section
|
|
className="w-full overflow-y-auto"
|
|
style={{ height: 'calc(100vh - 56px)', scrollbarWidth: 'none', padding: '16px 24px 32px 24px' }}
|
|
>
|
|
<div className="flex w-full max-w-none flex-col gap-0">
|
|
{/* Hero + KPI overlap — KPI bottom aligns with banner bottom */}
|
|
<div className="relative w-full overflow-hidden" style={{ height: '260px' }}>
|
|
<img
|
|
src="/archnest-hero-banner.png"
|
|
alt="ArchNest Banner"
|
|
className="absolute inset-0 h-full w-full"
|
|
style={{
|
|
objectFit: 'cover',
|
|
objectPosition: 'center 35%',
|
|
maskImage: 'linear-gradient(to bottom, black 0%, black 45%, transparent 95%)',
|
|
WebkitMaskImage: 'linear-gradient(to bottom, black 0%, black 45%, transparent 95%)',
|
|
}}
|
|
onError={(e) => {
|
|
const target = e.currentTarget
|
|
target.style.display = 'none'
|
|
target.parentElement!.classList.add('bg-card')
|
|
}}
|
|
/>
|
|
{/* Side vignette so the rectangular image blends into the page edges */}
|
|
<div
|
|
className="pointer-events-none absolute inset-0"
|
|
style={{
|
|
background:
|
|
'radial-gradient(ellipse 75% 100% at center, transparent 55%, var(--color-page) 100%)',
|
|
}}
|
|
/>
|
|
{/* KPI cards positioned so their bottom edge aligns with banner bottom */}
|
|
<div className="absolute bottom-0 left-0 right-0 z-10 px-4">
|
|
<StatusCards />
|
|
</div>
|
|
</div>
|
|
|
|
{/* 24px breathing room between KPI row and middle row */}
|
|
<div style={{ height: '24px' }} />
|
|
|
|
{/* Middle Row */}
|
|
<MiddleRow />
|
|
|
|
{/* Gap */}
|
|
<div style={{ height: '24px' }} />
|
|
|
|
{/* Bottom Row */}
|
|
<BottomRow />
|
|
</div>
|
|
</section>
|
|
</main>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default App
|