App Shell Layout
App shellsMITFull composable app shell with sidebar, navbar, page header, and body slots.
bun add @otfdashkit/ui
Preview
App Shell LayoutApp shells
Code
@otfdashkit/uiimport React, { useState } from 'react'
import { Home, Settings, Users, FileText, BarChart3, Bell, Search, Plus, LogOut } from 'lucide-react'
import { AppShell, AppShellSidebar, AppShellMain } from '@otfdashkit/ui/layouts-app-shell'
import { Sidebar, SidebarHeader, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupLabel, SidebarItem, SidebarSeparator } from '@otfdashkit/ui/layouts-sidebar'
import { Navbar, NavbarBrand, NavbarContent, NavbarItem } from '@otfdashkit/ui/layouts-navbar'
import { Page, PageHeader, PageTitle, PageDescription, PageActions, PageBody } from '@otfdashkit/ui/layouts-page'
const SidebarDemo = ({ collapsed, onCollapse }: { collapsed: boolean; onCollapse: () => void }) => (
<Sidebar collapsed={collapsed} onCollapse={onCollapse} width="220px">
<SidebarHeader>
{!collapsed && <span className="font-semibold text-sm text-[hsl(var(--foreground))]">MyApp</span>}
</SidebarHeader>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>Main</SidebarGroupLabel>
<SidebarItem icon={<Home size={16} />} label="Dashboard" active />
<SidebarItem icon={<BarChart3 size={16} />} label="Analytics" badge={3} />
<SidebarItem icon={<Users size={16} />} label="Team" />
<SidebarItem icon={<FileText size={16} />} label="Documents" />
</SidebarGroup>
<SidebarSeparator />
<SidebarGroup>
<SidebarGroupLabel>Account</SidebarGroupLabel>
<SidebarItem icon={<Bell size={16} />} label="Notifications" badge="9+" />
<SidebarItem icon={<Settings size={16} />} label="Settings" />
</SidebarGroup>
</SidebarContent>
<SidebarFooter>
<SidebarItem icon={<LogOut size={16} />} label="Sign out" />
</SidebarFooter>
</Sidebar>
)
export function Example() {
const [collapsed, setCollapsed] = useState(false)
return (
<div className="min-h-[500px] border border-[hsl(var(--border))] rounded-lg overflow-hidden">
<AppShell style={{ height: 500 }}>
<AppShellSidebar>
<SidebarDemo collapsed={collapsed} onCollapse={() => setCollapsed(v => !v)} />
</AppShellSidebar>
<AppShellMain>
<Navbar border sticky={false}>
<NavbarBrand><span className="font-semibold text-sm">Dashboard</span></NavbarBrand>
<NavbarContent align="end">
<NavbarItem><Search size={16} className="text-[hsl(var(--muted-foreground))]" /></NavbarItem>
<NavbarItem><Bell size={16} className="text-[hsl(var(--muted-foreground))]" /></NavbarItem>
</NavbarContent>
</Navbar>
<Page>
<PageHeader>
<div><PageTitle>Dashboard</PageTitle><PageDescription>Welcome back! Here's what's happening.</PageDescription></div>
<PageActions>
<button className="flex items-center gap-1.5 text-sm px-3 py-1.5 rounded-md bg-[hsl(var(--primary))] text-[hsl(var(--primary-foreground))]">
<Plus size={14} /> New Project
</button>
</PageActions>
</PageHeader>
<PageBody>
<div className="grid gap-4" style={{ gridTemplateColumns: 'repeat(auto-fill, minmax(min(100%, 200px), 1fr))' }}>
{['Projects', 'Team Members', 'Open Issues', 'Deployments'].map((label, i) => (
<div key={label} className="p-4 rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--card))]">
<div className="text-2xl font-bold text-[hsl(var(--foreground))]">{(i + 1) * 12}</div>
<div className="text-sm text-[hsl(var(--muted-foreground))]">{label}</div>
</div>
))}
</div>
</PageBody>
</Page>
</AppShellMain>
</AppShell>
</div>
)
}
Free with the SDK. This block ships in @otfdashkit/ui under the MIT license.
Props
Props declared in the AppShell source. Inherited HTML attributes are not listed.
| Prop | Type | Default | Description |
|---|---|---|---|
| defaultCollapsed | boolean | false |