Files
gridpilot.gg/apps/website/ui/Layout.tsx
2026-01-20 00:33:24 +01:00

84 lines
2.5 KiB
TypeScript

import { ReactNode } from 'react';
import { Box } from '@/ui/Box';
import { useSidebar } from '@/components/layout/SidebarContext';
export interface LayoutProps {
children: ReactNode;
header?: ReactNode;
footer?: ReactNode;
sidebar?: ReactNode;
fixedSidebar?: boolean;
fixedHeader?: boolean;
fixedFooter?: boolean;
}
/**
* Layout is the canonical app frame component.
* Redesigned for "Cockpit" layout: Sidebar is primary (full height), Header and Content sit to the right.
*/
export const Layout = ({
children,
header,
footer,
sidebar,
fixedSidebar = true,
fixedHeader = true,
fixedFooter = true
}: LayoutProps) => {
const { isCollapsed } = useSidebar();
const sidebarWidth = isCollapsed ? '20' : '64'; // 5rem vs 16rem
const sidebarWidthClass = isCollapsed ? 'lg:w-20' : 'lg:w-64';
const contentMarginClass = isCollapsed ? 'lg:ml-20' : 'lg:ml-64';
return (
<Box display="flex" minHeight="100vh" className="bg-base-black text-text-high">
{/* Sidebar - Primary Vertical Axis - Solid Background */}
{sidebar && (
<Box
as="aside"
width={sidebarWidth}
display={{ base: 'none', lg: 'block' }}
position={fixedSidebar ? "fixed" : "relative"}
top={0}
bottom={0}
left={0}
style={{ zIndex: 60, width: isCollapsed ? '5rem' : '16rem' }} // Explicit style for width transition
className={`bg-base-black border-r border-outline-steel transition-all duration-300 ease-in-out`}
>
{sidebar}
</Box>
)}
{/* Main Content Area - Right of Sidebar */}
<Box
display="flex"
flexDirection="col"
flex={1}
className={`transition-all duration-300 ease-in-out ${fixedSidebar && sidebar ? contentMarginClass : ''}`}
minWidth="0" // Prevent flex child overflow
>
{/* Header - Rendered directly as it contains AppShellBar (fixed) */}
{header}
{/* Main Scrollable Content */}
<Box
as="main"
flex={1}
display="flex"
flexDirection="col"
position="relative"
marginTop={fixedHeader ? 14 : 0} // Offset for fixed header (h-14)
paddingBottom={fixedFooter ? 14 : 0} // Offset for fixed footer (h-14)
>
<Box flex={1} p={0}>
{children}
</Box>
</Box>
{/* Footer - Rendered directly as it contains AppShellBar (fixed) */}
{footer}
</Box>
</Box>
);
};