84 lines
2.5 KiB
TypeScript
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>
|
|
);
|
|
};
|