KQ-1301 · APP/SHELL

App Shell

The frame a product's screens live in: a sidebar whose width is one motion value on glide, so its labels tuck away row by row and leave a 56px icon rail with tooltips, its edge dragged 1:1 and committed by projection with the release velocity; below 640px it becomes a drawer that slides over a scrim on glide and can be pushed back out. A pill under the current row travels on snap, pages change by slide, fade or zoom with the last crumb cross-fading in the same beat, and search is a combobox over the pages. Arrow keys walk the sidebar, [ or Cmd/Ctrl+B folds it, 1–9 change page and / goes to search.

KQ-1301 · APP/SHELL

Overview

Tuesday · seven jobs across three teams

Jobs today71 done
Out now21 on site
Running late1Call ahead
First-time fix92%Last 30 days

Completed this week

76 jobs

Recent activity

  1. 10:52Team North is 20 minutes late to 3 Quarry Lane
  2. 10:41Mira Chen set off for Basin Yard 2
  3. 10:05J-4102 closed with a signed sheet
  4. 09:12Tomas Reyes arrived at Larch Court
  5. 08:30Seven jobs dispatched for today

overview · seven jobs, three teams · 1 to 3 switch pages · [ folds the sidebar

Install

One command — the source lands in your repo. Or copy it from the Code tab.

$ pnpm dlx shadcn@latest add @kinetiq/app-shell

Props

pages
AppShellPage[]
default defaultShellPages
The destinations in sidebar order, each with its label, icon, optional badge and section, crumbs, heading, summary, search keywords and content.
page / defaultPage
string
default the first page
The current page's id. Controlled or uncontrolled.
onPageChange
(id: string) => void
default —
Fires from the row, crumb, shortcut or search result that chose a page.
collapsed / defaultCollapsed
boolean
default open from 1024px, folded below
The sidebar folded to its rail (or hidden without rail). Controlled or uncontrolled; left unset it follows the shell's width.
onCollapsedChange
(collapsed: boolean) => void
default —
Fires from the toggle, the edge drag, the edge's arrow keys or the shortcut, with the new fold.
rail
boolean
default true
Fold to a 56px icon rail whose labels become tooltips. Off: the sidebar slides away entirely and the content takes the width.
transition
"slide" | "fade" | "zoom"
default "slide"
How the content changes page: rising 16px in the direction of travel through the nav, a cross-fade, or settling from 0.98 scale.
density
"compact" | "cozy" | "roomy"
default "cozy"
Row heights (28/32/36px), the top bar (44/48/56px), paddings and the heading size.
workspace
AppShellWorkspace
default defaultShellWorkspace
The product at the top of the sidebar: name, detail line and an optional 28px mark.
user
AppShellUser
default defaultShellUser
Who is signed in, at the foot of the sidebar.
navLabel
string
default "Main"
The sidebar navigation's accessible name.
searchPlaceholder
string
default "Search " + workspace name
The search field's placeholder and accessible name.
onSearch
(query: string) => void
default —
Enter in search when no page matches, with the query.
shortcuts
boolean
default true
[ or Cmd/Ctrl+B folds the sidebar, 1–9 go to a page and / focuses search, while focus is in the shell or it is hovered with nothing focused; never while typing.
status
"ready" | "loading" | "error"
default "ready"
The content area's state: a skeleton while loading, a message with Retry on error. The sidebar keeps working.
onRetry
() => void
default —
The error state's Retry button.
label
string
default workspace name
The shell's accessible name.
sound
boolean
default false
A swish as the visitor folds or opens the sidebar or drawer, a click pitched by place as they choose a page.
className
string
default —
Classes for the root. It is 560px tall by default; pass a height (h-full, h-dvh) to fill a screen.