Extend Infrastructure hero banner to the top, overlapping the top bar

Moves the hero rendering to the layout level so the banner shows the
full golden arch and sky behind the page title, search bar, and
sub-tabs row. TopBar and the search input backgrounds are now
transparent so the banner reads through cleanly.
This commit is contained in:
Claude 2026-06-18 16:50:06 +00:00
parent 2c87c32fd7
commit 54b7aa1e32
No known key found for this signature in database
3 changed files with 73 additions and 68 deletions

View file

@ -1,5 +1,5 @@
import { useState } from 'react' import { useState } from 'react'
import { Routes, Route } from 'react-router-dom' import { Routes, Route, useLocation } from 'react-router-dom'
import Sidebar from './components/Sidebar' import Sidebar from './components/Sidebar'
import TopBar from './components/TopBar' import TopBar from './components/TopBar'
import Glance from './pages/Glance' import Glance from './pages/Glance'
@ -8,6 +8,8 @@ import Infrastructure from './pages/Infrastructure'
function App() { function App() {
const [sidebarCollapsed, setSidebarCollapsed] = useState(false) const [sidebarCollapsed, setSidebarCollapsed] = useState(false)
const sidebarWidth = sidebarCollapsed ? 64 : 200 const sidebarWidth = sidebarCollapsed ? 64 : 200
const location = useLocation()
const showHero = location.pathname === '/infrastructure'
return ( return (
<div className="min-h-screen w-screen overflow-hidden bg-page"> <div className="min-h-screen w-screen overflow-hidden bg-page">
@ -17,14 +19,38 @@ function App() {
/> />
<main <main
className="h-screen overflow-hidden" className="relative h-screen overflow-hidden"
style={{ marginLeft: `${sidebarWidth}px`, width: `calc(100vw - ${sidebarWidth}px)` }} style={{ marginLeft: `${sidebarWidth}px`, width: `calc(100vw - ${sidebarWidth}px)` }}
> >
{showHero && (
<div className="pointer-events-none absolute left-0 right-0 top-0" style={{ height: '300px', zIndex: 0 }}>
<img
src="/archnest-hero-banner.png"
alt=""
className="absolute inset-0 h-full w-full"
style={{
objectFit: 'cover',
objectPosition: 'center 5%',
maskImage: 'linear-gradient(to bottom, black 0%, black 55%, transparent 100%)',
WebkitMaskImage: 'linear-gradient(to bottom, black 0%, black 55%, transparent 100%)',
}}
/>
<div
className="absolute inset-0"
style={{
background: 'radial-gradient(ellipse 70% 100% at center, transparent 40%, var(--color-page) 100%)',
}}
/>
</div>
)}
<div className="relative" style={{ zIndex: 1 }}>
<TopBar /> <TopBar />
</div>
<section <section
className="flex w-full flex-col overflow-hidden" className="relative flex w-full flex-col overflow-hidden"
style={{ height: 'calc(100vh - 56px)', scrollbarWidth: 'none', padding: '16px 24px 24px 24px', gap: '20px' }} style={{ height: 'calc(100vh - 56px)', scrollbarWidth: 'none', padding: '16px 24px 24px 24px', gap: '20px', zIndex: 1 }}
> >
<Routes> <Routes>
<Route path="/" element={<Glance />} /> <Route path="/" element={<Glance />} />

View file

@ -28,7 +28,7 @@ export default function TopBar() {
}, []) }, [])
return ( return (
<header className="h-14 flex items-center px-6 bg-page sticky top-0 z-40"> <header className="h-14 flex items-center px-6 sticky top-0 z-40">
{/* Page Title — pushed away from sidebar edge */} {/* Page Title — pushed away from sidebar edge */}
<h1 className="text-[18px] font-bold uppercase tracking-wide" style={{ color: '#C8A434', marginLeft: '20px' }}> <h1 className="text-[18px] font-bold uppercase tracking-wide" style={{ color: '#C8A434', marginLeft: '20px' }}>
{title} {title}
@ -41,8 +41,8 @@ export default function TopBar() {
<input <input
type="text" type="text"
placeholder="Search resources..." placeholder="Search resources..."
className="w-[300px] h-8 rounded-full bg-card border border-border text-[12px] text-text-primary placeholder:text-text-secondary focus:outline-none focus:border-gold transition-colors" className="w-[300px] h-8 rounded-full border border-border text-[12px] text-text-primary placeholder:text-text-secondary focus:outline-none focus:border-gold transition-colors"
style={{ paddingLeft: '36px', paddingRight: '16px' }} style={{ paddingLeft: '36px', paddingRight: '16px', backgroundColor: 'rgba(255,255,255,0.04)', backdropFilter: 'blur(6px)' }}
/> />
</div> </div>
</div> </div>

View file

@ -117,28 +117,8 @@ export default function Infrastructure() {
return ( return (
<> <>
{/* Hero banner — faded seamlessly into the page background, no hard edges */} {/* Sub-tabs + Add Resource — hero banner is rendered at the layout level behind this */}
<div className="relative w-full shrink-0 overflow-hidden" style={{ height: '140px', margin: '-16px -24px 0 -24px' }}> <div className="flex items-center justify-between shrink-0">
<img
src="/archnest-hero-banner.png"
alt=""
className="absolute inset-0 h-full w-full"
style={{
objectFit: 'cover',
objectPosition: 'center 30%',
maskImage: 'linear-gradient(to bottom, transparent 0%, black 25%, black 55%, transparent 100%)',
WebkitMaskImage: 'linear-gradient(to bottom, transparent 0%, black 25%, black 55%, transparent 100%)',
}}
/>
<div
className="pointer-events-none absolute inset-0"
style={{
background: 'radial-gradient(ellipse 70% 100% at center, transparent 40%, var(--color-page) 100%)',
}}
/>
{/* Sub-tabs + Add Resource, overlaid on the banner */}
<div className="absolute bottom-0 left-0 right-0 z-10 flex items-center justify-between" style={{ padding: '0 24px 12px 24px' }}>
<div className="flex items-center gap-1 overflow-x-auto" style={{ scrollbarWidth: 'none' }}> <div className="flex items-center gap-1 overflow-x-auto" style={{ scrollbarWidth: 'none' }}>
{subTabs.map((tab) => { {subTabs.map((tab) => {
const active = tab === activeTab const active = tab === activeTab
@ -178,7 +158,6 @@ export default function Infrastructure() {
Add Resource Add Resource
</button> </button>
</div> </div>
</div>
{/* Status Cards */} {/* Status Cards */}
<div className="grid w-full grid-cols-5 gap-5 shrink-0"> <div className="grid w-full grid-cols-5 gap-5 shrink-0">