AppShell
AppShell
<AppShell header={<TopBar onMenuClick={() => setOpen(true)} />} sidebar={ <Sidebar> <Sidebar.Group> <Sidebar.Item href="/" active>Dashboard</Sidebar.Item> <Sidebar.Item href="/users">Users</Sidebar.Item> </Sidebar.Group> </Sidebar> }> <PageHeader title="Dashboard" /> {/* page content */}</AppShell>Mobile drawer
const [open, setOpen] = useState(false);<> <AppShell header={<TopBar onMenu={() => setOpen(true)} />} sidebar={<Sidebar>…</Sidebar>}> {content} </AppShell> <Sheet side="start" isOpen={open} onOpenChange={setOpen}> <Sidebar>…</Sidebar> </Sheet></>Install: @helixui/core
import { AppShell } from '@helixui/core'status: stable · since: 0.2.0
Tags: layout, shell, header, sidebar, responsive, top-level
Anatomy
┌─ header (sticky top) ────────────────────────────────┐│ logo … search … avatar │├──────────┬───────────────────────────────────────────┤│ sidebar │ <main> ││ (≥768px) │ PageHeader ││ │ <page content> ││ │ ││ │ │└──────────┴───────────────────────────────────────────┘ ↑ sidebar collapses below collapseBreakpoint; ↑ caller must render hamburger + Sheet for mobile.Layout
- display —
grid - width —
fill - height —
fill - intrinsicSize —
fills viewport, sidebar 240px (configurable), header sticky top - stackable —
false - fullBleed —
true
Visual
A desktop-first chrome: a sticky top header (border-bottom by border.default), a fixed-width sidebar on the
left, and a scrolling main column. Below collapseBreakpoint the sidebar disappears and main becomes
full-bleed; the caller is responsible for wiring a hamburger + Sheet drawer to expose it again.
Props
| Name | Type | Default | Description |
|---|---|---|---|
sidebar | ReactNode | — | Left rail content. Shown on desktop, hidden below the breakpoint. |
header | ReactNode | — | Sticky top bar. |
sidebarWidth | number | string | 240 | Sidebar width. Number → px. |
collapseBreakpoint | number | 768 | Min viewport (px) for sidebar to be visible. |
Slots
- children — main content area
Tokens used
color.bg.surface.default, color.text.primary, color.border.default
Accessibility
Notes
- Sidebar uses
<aside>; main uses<main>. Wrap nav inside the sidebar in<nav aria-label>(helixui Sidebar component does this). - On mobile the sidebar is
display:none. To expose it, render a hamburger inheaderthat opens aSheet side="start"with the same sidebar content.
Composes with
| Component | Relation | Note |
|---|---|---|
Sidebar | slot | Fills the sidebar prop. |
PageHeader | child | Common first child of children to title each route. |
Sheet | sibling | Pair with Sheet (side=‘start’) for the mobile sidebar drawer. |
SafeArea | parent | Wrap AppShell in SafeArea on mobile builds. |
Prompt examples
These are the AI prompt → JSX mappings used by the helixui prompt DSL and integrations like Cursor / Claude Code.
scaffold a logged-in app layout
“give me an app layout with a top bar and side nav”
<AppShell header={<TopBar />} sidebar={<Sidebar><Sidebar.Group><Sidebar.Item href="/" active>Home</Sidebar.Item></Sidebar.Group></Sidebar>}> <PageHeader title="Home" /> {/* page */}</AppShell>responsive — show the sidebar in a drawer on mobile
“make the sidebar slide in on mobile”
const [open, setOpen] = useState(false);<> <AppShell header={<TopBar onMenu={() => setOpen(true)} />} sidebar={<Sidebar>…</Sidebar>} > {content} </AppShell> <Sheet side="start" isOpen={open} onOpenChange={setOpen}> <Sidebar>…</Sidebar> </Sheet></>narrow icon-only sidebar
“use a 64px icon-only sidebar”
<AppShell sidebarWidth={64} sidebar={<IconRail />}> ...</AppShell>