AppShell
Layout-only foundations for rail, sidebar, main content, and optional panels.
Click the control to collapse the sidebar
Controls
import {
AppShellMainSlot,
AppShellOverlaySlot,
AppShellPanelSlot,
AppShellRailSlot,
AppShellRoot,
AppShellSidebarSlot,
} from "raft-ui";
<AppShellRoot>
<AppShellRailSlot>...</AppShellRailSlot>
<AppShellSidebarSlot>...</AppShellSidebarSlot>
<AppShellMainSlot overlay>
...
<AppShellOverlaySlot>...</AppShellOverlaySlot>
</AppShellMainSlot>
<AppShellPanelSlot>...</AppShellPanelSlot>
</AppShellRoot>AppShell hides the rail and sidebar and switches to a column below md. Keep the active page in AppShellMainSlot and add mobile navigation with md:hidden.
apps/doc/src/modules/app-shell/compositions/responsive.composition.tsx
export function AppShellResponsiveComposition() {
return (
<AppShellRoot className="min-h-dvh">
<AppShellRailSlot className="in-data-[theme=brutal]:border-r-2 in-data-[theme=brutal]:border-black">
<nav className="w-16 [[data-theme=elegant]_&]:w-14" aria-label="Workspace navigation">
Rail
</nav>
</AppShellRailSlot>
<AppShellSidebarSlot className="in-data-[theme=brutal]:border-r-2 in-data-[theme=brutal]:border-black">
<div className="w-60 in-data-[theme=elegant]:w-[252px]">Conversation list</div>
</AppShellSidebarSlot>
<AppShellMainSlot>
<div>Conversation</div>
</AppShellMainSlot>
<MobileNavRoot className="order-last md:hidden" aria-label="Primary navigation">
<MobileNavItem selected>
<MobileNavLabel>Messages</MobileNavLabel>
</MobileNavItem>
</MobileNavRoot>
</AppShellRoot>
);
}API#WIP
| Prop | Type | Default | Description |
|---|---|---|---|
sidebarCollapsible | boolean | false | When true, coordinates sidebar visibility and measures sidebar width for the main-panel transition. |
sidebarOpen | boolean | — | Controlled sidebar visibility when sidebarCollapsible is enabled. |
defaultSidebarOpen | boolean | true | Initial sidebar visibility for uncontrolled usage. |
onSidebarOpenChange | (open: boolean) => void | — | Called when a collapsible sidebar opens or closes. |
...props | useRender.ComponentProps<"div"> | — | Owns the responsive row-to-column layout and top safe-area inset. |
| Prop | Type | Default | Description |
|---|---|---|---|
...props | useRender.ComponentProps<"aside"> | — | Desktop rail column by default. Mount a separate instance with className for mobile bottom navigation; visibility stays caller-owned. |
| Prop | Type | Default | Description |
|---|---|---|---|
overlay | boolean | false | Provides the positioning context for an AppShellOverlaySlot rendered inside the main region. |
...props | useRender.ComponentProps<"main"> | — | Flexible primary content region. In a collapsible desktop layout, mount it inside a relative main panel so it can expand over the sidebar. |
| Prop | Type | Default | Description |
|---|---|---|---|
...props | useRender.ComponentProps<"div"> | — | Layout-only overlay region for temporarily covering the primary content without changing the column layout. Its child owns the surface and edges. |
| Prop | Type | Default | Description |
|---|---|---|---|
...props | useRender.ComponentProps<"aside"> | — | Optional secondary column. Place it in a caller-owned ResizablePanel when the user can adjust the split; the caller owns its width and surface. |