diff --git a/apps/website/app/layout.tsx b/apps/website/app/layout.tsx
index fe418d98f..e317994bc 100644
--- a/apps/website/app/layout.tsx
+++ b/apps/website/app/layout.tsx
@@ -75,7 +75,7 @@ export default async function RootLayout({
-
+
{children}
diff --git a/apps/website/components/app/AppShell.tsx b/apps/website/components/app/AppShell.tsx
deleted file mode 100644
index 3e6d0ca32..000000000
--- a/apps/website/components/app/AppShell.tsx
+++ /dev/null
@@ -1,30 +0,0 @@
-import React from 'react';
-import { Box } from '@/ui/Box';
-
-interface AppShellProps {
- children: React.ReactNode;
-}
-
-/**
- * AppShell is the root container for the entire application layout.
- * Provides the base structure with cockpit-inspired design.
- */
-export function AppShell({ children }: AppShellProps) {
- return (
-
- {children}
-
- );
-}
\ No newline at end of file
diff --git a/apps/website/components/layout/AppFooter.tsx b/apps/website/components/layout/AppFooter.tsx
index e0d794c35..829780307 100644
--- a/apps/website/components/layout/AppFooter.tsx
+++ b/apps/website/components/layout/AppFooter.tsx
@@ -12,7 +12,7 @@ export function AppFooter() {
variant="precision"
paddingY={6}
paddingX={6}
- borderTop={true}
+ borderTop
backgroundColor="rgba(10, 10, 11, 0.92)"
className="backdrop-blur-xl"
style={{
@@ -24,7 +24,7 @@ export function AppFooter() {
© {new Date().getFullYear()} GridPilot
-
+
Session ready
@@ -32,7 +32,7 @@ export function AppFooter() {
-
+
System Normal
diff --git a/apps/website/components/layout/AppHeader.tsx b/apps/website/components/layout/AppHeader.tsx
index 112025b09..d3f8ef5e1 100644
--- a/apps/website/components/layout/AppHeader.tsx
+++ b/apps/website/components/layout/AppHeader.tsx
@@ -21,17 +21,11 @@ export function AppHeader() {
{/* Left: Brand & Context */}
@@ -44,9 +38,9 @@ export function AppHeader() {
alignItems="center"
gap={3}
paddingLeft={4}
- borderLeft={true}
- h="24px"
- style={{ borderLeftColor: 'var(--ui-color-border-muted)' }}
+ borderLeft
+ h="6"
+ borderColor="var(--ui-color-border-muted)"
>
Workspace
@@ -65,7 +59,7 @@ export function AppHeader() {
{/* Right: Session Controls */}
-
+
LIVE
diff --git a/apps/website/components/layout/AppSidebar.tsx b/apps/website/components/layout/AppSidebar.tsx
index 058ae4164..827ba9c84 100644
--- a/apps/website/components/layout/AppSidebar.tsx
+++ b/apps/website/components/layout/AppSidebar.tsx
@@ -18,23 +18,19 @@ export function AppSidebar() {
-
+
DASHBOARD
diff --git a/apps/website/components/layout/MainContent.tsx b/apps/website/components/layout/MainContent.tsx
deleted file mode 100644
index ad1d5df38..000000000
--- a/apps/website/components/layout/MainContent.tsx
+++ /dev/null
@@ -1,54 +0,0 @@
-'use client';
-
-import { Box } from '@/ui/Box';
-import { ReactNode } from 'react';
-
-interface MainContentProps {
- children: ReactNode;
- hasSidebar: boolean;
-}
-
-export function MainContent({ children, hasSidebar }: MainContentProps) {
- return (
-
-
- {/* Background Grid */}
-
-
- {/* Content */}
-
- {children}
-
-
-
- );
-}
diff --git a/apps/website/templates/layout/RootAppShellTemplate.tsx b/apps/website/templates/layout/RootAppShellTemplate.tsx
index bd37185c4..728328aab 100644
--- a/apps/website/templates/layout/RootAppShellTemplate.tsx
+++ b/apps/website/templates/layout/RootAppShellTemplate.tsx
@@ -1,13 +1,12 @@
'use client';
-import { AppShell } from '@/components/app/AppShell';
import { AppFooter } from '@/components/layout/AppFooter';
import { AppHeader } from '@/components/layout/AppHeader';
import { AppSidebar } from '@/components/layout/AppSidebar';
-import { MainContent } from '@/components/layout/MainContent';
import { useCurrentSession } from '@/hooks/auth/useCurrentSession';
import { routes } from '@/lib/routing/RouteConfig';
-import { ContentViewport } from '@/ui/ContentViewport';
+import { Layout } from '@/ui/Layout';
+import { Container } from '@/ui/Container';
import { usePathname } from 'next/navigation';
import React from 'react';
@@ -17,11 +16,7 @@ export interface RootAppShellViewData {
/**
* RootAppShellTemplate orchestrates the top-level semantic shells of the application.
- * It follows the "Telemetry Workspace" structure:
- * - AppHeader = header/control bar
- * - AppSidebar = sidebar rail
- * - MainContent = content area wrapper
- * - AppFooter = footer
+ * It uses the canonical ui/Layout component to define the app frame.
*/
export function RootAppShellTemplate({ children }: RootAppShellViewData) {
const pathname = usePathname();
@@ -33,20 +28,19 @@ export function RootAppShellTemplate({ children }: RootAppShellViewData) {
const showSidebar = isAuthenticated && !isLandingPage;
return (
-
-
-
- {showSidebar && }
-
-
-
- {children}
-
-
-
-
+ }
+ sidebar={showSidebar ? : undefined}
+ footer={}
+ fixedHeader
+ fixedSidebar
+ >
+
+ {children}
+
+
);
}
diff --git a/apps/website/ui/ContentViewport.tsx b/apps/website/ui/ContentViewport.tsx
deleted file mode 100644
index e8576df95..000000000
--- a/apps/website/ui/ContentViewport.tsx
+++ /dev/null
@@ -1,31 +0,0 @@
-import { ReactNode } from 'react';
-import { Box, type Spacing } from './Box';
-
-export interface ContentViewportProps {
- children: ReactNode;
- padding?: 'none' | 'sm' | 'md' | 'lg';
- fullWidth?: boolean;
-}
-
-export const ContentViewport = ({
- children,
- padding = 'md',
- fullWidth = false,
-}: ContentViewportProps) => {
- const paddingMap: Record, Spacing> = {
- none: 0,
- sm: 4,
- md: 8,
- lg: 12,
- };
-
- const maxWidth = fullWidth ? '100%' : '80rem';
-
- return (
-
-
- {children}
-
-
- );
-};
\ No newline at end of file
diff --git a/apps/website/ui/Layout.tsx b/apps/website/ui/Layout.tsx
index f125ee5a5..ff515d28c 100644
--- a/apps/website/ui/Layout.tsx
+++ b/apps/website/ui/Layout.tsx
@@ -6,39 +6,79 @@ export interface LayoutProps {
header?: ReactNode;
footer?: ReactNode;
sidebar?: ReactNode;
+ /**
+ * Whether the sidebar should be fixed to the side.
+ * If true, the main content will be offset by the sidebar width.
+ */
+ fixedSidebar?: boolean;
+ /**
+ * Whether the header should be fixed to the top.
+ * If true, the main content will be offset by the header height.
+ */
+ fixedHeader?: boolean;
}
+/**
+ * Layout is the canonical app frame component.
+ * It orchestrates the high-level structure: Header, Sidebar, Main Content, and Footer.
+ */
export const Layout = ({
children,
header,
footer,
- sidebar
+ sidebar,
+ fixedSidebar = false,
+ fixedHeader = false
}: LayoutProps) => {
return (
-
+
{header && (
-
+
{header}
)}
-
+
{sidebar && (
-
+
{sidebar}
)}
-
- {children}
+
+
+ {children}
+
+
+ {footer && (
+
+ {footer}
+
+ )}
-
- {footer && (
-
- {footer}
-
- )}
);
};