App Shell
A full-page application layout with header, collapsible sidebar, and content area. Built using Box, Column, Row, and Button components.
My Application
Dashboard
Users
Settings
Main content area
Source
'use client';
import { createContext, useContext, useState } from 'react';
import { Box, Button, Column, Icon, Row } from '@umami/react-zen';
import { PanelLeft } from 'lucide-react';
const AppShellContext = createContext({
isSidebarOpen: true,
setSidebarOpen: () => {},
});
export function useAppShell() {
return useContext(AppShellContext);
}
export function AppShell({ defaultSidebarOpen = true, children, ...props }) {
const [isSidebarOpen, setSidebarOpen] = useState(defaultSidebarOpen);
return (
<AppShellContext.Provider value={{ isSidebarOpen, setSidebarOpen }}>
<Box height="100%" {...props}>
<Column height="100%">{children}</Column>
</Box>
</AppShellContext.Provider>
);
}
export function AppShellHeader({ children }) {
return (
<Row
paddingX="4"
paddingY="3"
alignItems="center"
justifyContent="space-between"
backgroundColor="surface-raised"
borderColor="muted"
border="bottom"
>
{children}
</Row>
);
}
export function AppShellBody({ children }) {
return (
<Row flexGrow="1" overflow="hidden">
{children}
</Row>
);
}
export function AppShellSidebar({ width = '14rem', children, ...props }) {
const { isSidebarOpen } = useAppShell();
if (!isSidebarOpen) return null;
return (
<Box
width={width}
height="100%"
backgroundColor="surface-raised"
borderColor="muted"
border="right"
flexShrink="0"
overflow="auto"
{...props}
>
{children}
</Box>
);
}
export function AppShellContent({ children, ...props }) {
return (
<Box flexGrow="1" overflow="auto" {...props}>
{children}
</Box>
);
}
export function AppShellSidebarToggle() {
const { isSidebarOpen, setSidebarOpen } = useAppShell();
return (
<Button variant="quiet" onPress={() => setSidebarOpen(!isSidebarOpen)}>
<Icon style={{ transform: isSidebarOpen ? undefined : 'scaleX(-1)' }}>
<PanelLeft />
</Icon>
</Button>
);
}Variations
With navigation
Dashboard
Dashboard
Users
Settings
Main content area
Sidebar closed by default
Compact View
Click the toggle to show sidebar