fix: proper dashboard layout — header + sidebar + content fill viewport
Use h-screen overflow-hidden on the root container for authenticated views. Sidebar and content fill the remaining height below the header. Remove footer from dashboard pages. Content scrolls inside its own container, sidebar stays fixed in place.
This commit is contained in:
@@ -112,65 +112,66 @@ function LayoutInner({ children }: { children: React.ReactNode }) {
|
||||
return <LoadingOverlay logoSrc="/pulse_icon_no_margins.png" title="Pulse" portal={false} />
|
||||
}
|
||||
|
||||
const headerElement = (
|
||||
<Header
|
||||
auth={auth}
|
||||
LinkComponent={Link}
|
||||
logoSrc="/pulse_icon_no_margins.png"
|
||||
appName="Pulse"
|
||||
variant={isAuthenticated ? 'static' : 'floating'}
|
||||
orgs={orgs}
|
||||
activeOrgId={auth.user?.org_id}
|
||||
onSwitchOrganization={handleSwitchOrganization}
|
||||
onCreateOrganization={handleCreateOrganization}
|
||||
allowPersonalOrganization={false}
|
||||
showFaq={false}
|
||||
showSecurity={false}
|
||||
showPricing={true}
|
||||
topOffset={!isAuthenticated && showOfflineBar ? '2.5rem' : undefined}
|
||||
rightSideActions={auth.user ? <NotificationCenter /> : null}
|
||||
apps={CIPHERA_APPS}
|
||||
currentAppId="pulse"
|
||||
onOpenSettings={openSettings}
|
||||
leftActions={isAuthenticated ? <MobileSidebarToggle /> : undefined}
|
||||
customNavItems={
|
||||
<>
|
||||
{!auth.user && (
|
||||
<Link
|
||||
href="/features"
|
||||
className="px-4 py-2 text-sm font-medium text-neutral-600 dark:text-neutral-400 hover:text-neutral-900 dark:hover:text-white rounded-lg hover:bg-neutral-100/50 dark:hover:bg-neutral-800/50 transition-all duration-200"
|
||||
>
|
||||
Features
|
||||
</Link>
|
||||
)}
|
||||
</>
|
||||
}
|
||||
/>
|
||||
)
|
||||
|
||||
if (isAuthenticated) {
|
||||
// Dashboard layout: header pinned, sidebar + content fill remaining viewport
|
||||
return (
|
||||
<div className="flex flex-col h-screen overflow-hidden">
|
||||
{auth.user && <OfflineBanner isOnline={isOnline} />}
|
||||
<div className="shrink-0">{headerElement}</div>
|
||||
{children}
|
||||
<SettingsModalWrapper />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// Public/marketing layout: floating header, scrollable page, footer
|
||||
return (
|
||||
<div className="flex flex-col min-h-screen">
|
||||
{auth.user && <OfflineBanner isOnline={isOnline} />}
|
||||
<Header
|
||||
auth={auth}
|
||||
{headerElement}
|
||||
<main className="flex-1 pb-8 pt-24">
|
||||
{children}
|
||||
</main>
|
||||
<Footer
|
||||
LinkComponent={Link}
|
||||
logoSrc="/pulse_icon_no_margins.png"
|
||||
appName="Pulse"
|
||||
variant={isAuthenticated ? 'static' : 'floating'}
|
||||
orgs={orgs}
|
||||
activeOrgId={auth.user?.org_id}
|
||||
onSwitchOrganization={handleSwitchOrganization}
|
||||
onCreateOrganization={handleCreateOrganization}
|
||||
allowPersonalOrganization={false}
|
||||
showFaq={false}
|
||||
showSecurity={false}
|
||||
showPricing={true}
|
||||
topOffset={!isAuthenticated && showOfflineBar ? '2.5rem' : undefined}
|
||||
rightSideActions={auth.user ? <NotificationCenter /> : null}
|
||||
apps={CIPHERA_APPS}
|
||||
currentAppId="pulse"
|
||||
onOpenSettings={openSettings}
|
||||
leftActions={isAuthenticated ? <MobileSidebarToggle /> : undefined}
|
||||
customNavItems={
|
||||
<>
|
||||
{!auth.user && (
|
||||
<Link
|
||||
href="/features"
|
||||
className="px-4 py-2 text-sm font-medium text-neutral-600 dark:text-neutral-400 hover:text-neutral-900 dark:hover:text-white rounded-lg hover:bg-neutral-100/50 dark:hover:bg-neutral-800/50 transition-all duration-200"
|
||||
>
|
||||
Features
|
||||
</Link>
|
||||
)}
|
||||
</>
|
||||
}
|
||||
isAuthenticated={false}
|
||||
/>
|
||||
{isAuthenticated ? (
|
||||
// Authenticated: sidebar layout — children include DashboardShell
|
||||
<>{children}</>
|
||||
) : (
|
||||
// Public: standard content with footer
|
||||
<>
|
||||
<main className="flex-1 pb-8 pt-24">
|
||||
{children}
|
||||
</main>
|
||||
<Footer
|
||||
LinkComponent={Link}
|
||||
appName="Pulse"
|
||||
isAuthenticated={false}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{isAuthenticated && (
|
||||
<Footer
|
||||
LinkComponent={Link}
|
||||
appName="Pulse"
|
||||
isAuthenticated={true}
|
||||
/>
|
||||
)}
|
||||
<SettingsModalWrapper />
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -13,9 +13,9 @@ export default function DashboardShell({
|
||||
const { mobileOpen, closeMobile } = useSidebar()
|
||||
|
||||
return (
|
||||
<div className="flex flex-1">
|
||||
<div className="flex flex-1 overflow-hidden">
|
||||
<Sidebar siteId={siteId} mobileOpen={mobileOpen} onMobileClose={closeMobile} />
|
||||
<main className="flex-1 min-w-0 pb-8">
|
||||
<main className="flex-1 min-w-0 overflow-y-auto">
|
||||
{children}
|
||||
</main>
|
||||
</div>
|
||||
|
||||
@@ -319,7 +319,7 @@ export default function Sidebar({
|
||||
|
||||
{/* Desktop sidebar */}
|
||||
<aside
|
||||
className={`hidden lg:flex flex-col shrink-0 sticky top-0 h-screen border-r border-neutral-200 dark:border-neutral-800 bg-white dark:bg-neutral-900 transition-[width] duration-200 overflow-hidden ${
|
||||
className={`hidden lg:flex flex-col shrink-0 border-r border-neutral-200 dark:border-neutral-800 bg-white dark:bg-neutral-900 transition-[width] duration-200 overflow-hidden ${
|
||||
collapsed ? 'w-[68px]' : 'w-60'
|
||||
}`}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user