Shell
App shell layout with sidebar and header
Shell
The Shell component provides the standard application layout with sidebar navigation, top header, and main content area. It's the structural foundation for all authenticated views.
Type Signature
interface ShellProps {
/** Show sidebar */
sidebar?: boolean
/** Show header */
header?: boolean
/** Sidebar collapsed by default */
sidebarCollapsed?: boolean
/** Child content */
children: React.ReactNode
}Usage
<App name="Acme Dashboard">
<Shell>
<Dashboard />
</Shell>
</App>Props
sidebar
Controls whether the sidebar is rendered. Defaults to true.
// Show sidebar (default)
<Shell>
<Dashboard />
</Shell>
// Hide sidebar
<Shell sidebar={false}>
<Dashboard />
</Shell>header
Controls whether the header is rendered. Defaults to true.
// Show header (default)
<Shell>
<Dashboard />
</Shell>
// Hide header
<Shell header={false}>
<Dashboard />
</Shell>sidebarCollapsed
Sets the initial collapsed state of the sidebar. Defaults to false.
// Sidebar expanded (default)
<Shell>
<Dashboard />
</Shell>
// Sidebar collapsed by default
<Shell sidebarCollapsed={true}>
<Dashboard />
</Shell>children
The main content area. Typically contains View components like Dashboard, Settings, etc.
<Shell>
<Dashboard>
{/* Dashboard content */}
</Dashboard>
</Shell>Layout Structure
The Shell component implements this layout:
┌─────────────────────────────────────┐
│ Header │
├──────────┬──────────────────────────┤
│ │ │
│ Sidebar │ Main │
│ │ │
│ │ │
└──────────┴──────────────────────────┘With Collapsed Sidebar
When the sidebar is collapsed, it shows icons only:
┌─────────────────────────────────────┐
│ Header │
├───┬─────────────────────────────────┤
│ S │ │
│ i │ Main │
│ d │ │
│ e │ │
└───┴─────────────────────────────────┘Header Hidden
When the header is hidden:
┌──────────┬──────────────────────────┐
│ │ │
│ Sidebar │ Main │
│ │ │
│ │ │
└──────────┴──────────────────────────┘Full-Screen Mode
When both sidebar and header are hidden:
┌─────────────────────────────────────┐
│ │
│ Main │
│ │
│ │
└─────────────────────────────────────┘Common Patterns
Standard Application Layout
Most applications use the default Shell configuration:
<App name="Acme Dashboard">
<Shell>
<Dashboard />
</Shell>
</App>Full-Screen View
For immersive experiences (editors, canvas, etc.):
<Shell sidebar={false} header={false}>
<EditorView />
</Shell>Presentation Mode
Hide sidebar but keep header for context:
<Shell sidebar={false}>
<PresentationView />
</Shell>Compact Mode
Start with sidebar collapsed for more content space:
<Shell sidebarCollapsed={true}>
<Dashboard />
</Shell>View Layouts
The Shell provides the container, but Views determine their internal layout:
Single Layout
┌─────────────────────────────────┐
│ main │
└─────────────────────────────────┘Example: Dashboard, Settings
Column Layout
┌───────────────┬─────────────────┐
│ sidebar │ main │
└───────────────┴─────────────────┘Example: List + Detail views
Canvas Layout
┌─────────────────────────────────┐
│ top │
├─────────┬───────────────────────┤
│ sidebar │ main │
└─────────┴───────────────────────┘Example: Workflow editor, Design tools
Vibe Layout
┌─────────┬───────────┬──────────┐
│ chat │ preview │ code │
└─────────┴───────────┴──────────┘Example: VibeCode editor
See View Layouts for complete details.
Responsive Behavior
The Shell adapts to different screen sizes:
Desktop (≥1024px)
┌────────────────────────────────────┐
│ Header │
├─────────┬──────────────────────────┤
│ Sidebar │ Main │
│ (240px) │ │
└─────────┴──────────────────────────┘Tablet (768px - 1023px)
┌────────────────────────────────────┐
│ Header │
├───┬────────────────────────────────┤
│ S │ Main │
│ b │ │
└───┴────────────────────────────────┘
Sidebar collapsed to icons (60px)Mobile (under 768px)
┌────────────────────────────────────┐
│ ☰ Header │
├────────────────────────────────────┤
│ │
│ Main │
│ │
└────────────────────────────────────┘
Sidebar slides over as drawerState Management
The Shell manages several pieces of UI state:
Sidebar State
interface SidebarState {
collapsed: boolean // Is sidebar collapsed?
mobile: boolean // Is mobile drawer open?
width: number // Sidebar width in pixels
}Navigation State
interface NavigationState {
currentPath: string // Active route
breadcrumbs: Crumb[] // Breadcrumb trail
}Customization
Custom Sidebar Width
Override the default sidebar width:
<Shell className="[--sidebar-width:280px]">
<Dashboard />
</Shell>Custom Breakpoints
Control when sidebar collapses:
<Shell className="[--sidebar-collapse-at:900px]">
<Dashboard />
</Shell>Integration with Components
Sidebar Component
The Shell automatically renders the <Sidebar> component with navigation items:
// Shell internally does:
<Sidebar
nav={navigationItems}
collapsed={sidebarCollapsed}
onCollapse={handleCollapse}
/>Header Component
The Shell automatically renders the <Header> component:
// Shell internally does:
<Header
breadcrumbs={currentBreadcrumbs}
user={currentUser}
/>Best Practices
Keep Shell Minimal
The Shell should only contain layout logic, not business logic:
// Good
<Shell>
<Dashboard />
</Shell>
// Bad - don't add complex logic to Shell
<Shell>
{isLoading ? <Spinner /> : <Dashboard />}
</Shell>Use View Components for Content
Wrap content in semantic View components:
// Good
<Shell>
<DashboardView>
<MetricsPanel />
<ChartPanel />
</DashboardView>
</Shell>
// Bad - don't put raw content in Shell
<Shell>
<div>
<h1>Dashboard</h1>
<p>Metrics...</p>
</div>
</Shell>Handle Mobile Navigation
Ensure navigation works on mobile:
<Shell>
{/* Shell handles mobile drawer automatically */}
<Dashboard />
</Shell>Accessibility
The Shell component implements several accessibility features:
- Landmark regions -
<nav>,<header>,<main> - Skip links - Jump to main content
- Keyboard navigation - Focus management
- Screen reader labels - Descriptive ARIA labels
<div role="application">
<a href="#main" class="skip-link">Skip to content</a>
<header role="banner">
<!-- Header content -->
</header>
<nav role="navigation" aria-label="Main navigation">
<!-- Sidebar navigation -->
</nav>
<main id="main" role="main">
<!-- Main content -->
</main>
</div>