npx shadcn@latest add https://sdk-components.thesqd.com/r/app-sidebar.jsonimport { Sidebar } from "@/components/blocks/app-sidebar";import { Sidebar } from "@/components/blocks/app-sidebar";
export function AppShell() {
return (
<div className="h-screen w-full">
<Sidebar
workspaces={[{ id: "default", name: "TheSquad", logoSrc: "/sqd-logo.png" }]}
groups={[{ label: "Favorites", items: [{ name: "Design Engineering", href: "#" }] }]}
>
<main className="p-8">Content area</main>
</Sidebar>
</div>
);
}Sidebar (shell — owns collapse, peek, resize)
├── children (content area — reflows around the sidebar)
├── aside (docked sidebar, slides off-frame when collapsed)
│ ├── Brand row (workspaces + workspaceMenu dropdown, collapse button)
│ ├── Tabs (variant="rounded" — tabs prop; active expands)
│ ├── Nav (groups → items → children, actions on hover)
│ └── Footer (footer prop)
├── Resize handle (resizable — drag the right edge)
└── Peek panel (peek — floating preview while collapsed)| Prop | Type | Default | Description |
|---|---|---|---|
workspaces | SidebarWorkspace[] | — | Switchable workspaces listed in the brand dropdown. |
workspace | string | — | Controlled active workspace id. |
defaultWorkspace | string | workspaces[0].id | Uncontrolled initial workspace. |
onWorkspaceChange | (id: string) => void | — | Fires when a workspace is selected. |
workspaceMenu | SidebarMenuItem[] | — | Extra entries appended under the workspace list (Settings, Sign out, …). |
tabs | SidebarTab[] | — | Rounded icon tabs under the brand row. Omit to hide the strip. |
tab | string | — | Controlled active tab value. |
defaultTab | string | tabs[0].value | Uncontrolled initial tab. |
onTabChange | (value: string) => void | — | Fires when a tab is selected. |
groups | SidebarNavGroup[] | [] | Nav groups rendered in the scroll area. |
footer | React.ReactNode | — | Pinned footer content (buttons, user menu, …). |
collapsible | boolean | true | Allow collapsing the sidebar off-frame. |
collapsed | boolean | — | Controlled collapsed state. |
defaultCollapsed | boolean | false | Uncontrolled initial collapsed state. |
onCollapsedChange | (collapsed: boolean) => void | — | Fires when the sidebar collapses or expands. |
peek | boolean | true | Reveal a floating preview when hovering the reopen toggle while collapsed. |
resizable | boolean | true | Drag the right edge to resize between minWidth and maxWidth. |
minWidth | number | 274 | Narrowest sidebar width in px. |
maxWidth | number | 408 | Widest sidebar width in px. At this width every tab reveals its label. |
defaultWidth | number | minWidth | Initial sidebar width in px. |
reserveTitlebar | boolean | false | Pad the brand row so macOS traffic lights sit inside the sidebar (Tauri). |
className | string | — | Class override for the shell wrapper. |
children | React.ReactNode | — | Content area to the right of the sidebar — reflows when it collapses. |
| Prop | Type | Default | Description |
|---|---|---|---|
SidebarWorkspace | { id, name, logoSrc?, account? } | — | `logoSrc` renders an image mark; `account` renders the number as small grey text. |
SidebarTab | { value, label, icon? } | — | One rounded icon tab. |
SidebarNavGroup | { label?, items, more? } | — | `more: true` appends an inert “More” row; pass `{ label, onClick }` to wire it up. |
SidebarNavItem | { name, icon?, href?, onClick?, children?, actions? } | — | `children` makes the row collapsible; `actions` adds a hover “…” dropdown. |
SidebarMenuItem | "separator" | { heading } | { label, icon?, onClick?, variant?, disabled? } | — | Dropdown entry — same spec as DropdownMenu `items`. |