Sidebar
Navigates a console from a left rail that folds between labelled rows and icons.
Configurations
Supported configurations for this component.
Configurations
5 examplesAdd to your project
One command adds this component to your project.
Run the following command. New project? Run npx shadcn@latest init first to set up Tailwind and path aliases.
npx shadcn@latest add @aicanvas/••••••••••••Light and dark both come with the install and follow the dark class on <html>, the shadcn dark mode setup (next-themes with attribute="class").
Props
Every prop this component accepts. Any other prop is forwarded to the underlying element.
SidebarItem
| Prop | Type | Default | Description |
|---|---|---|---|
| labelreq | string | - | Row label; also the row's React key and its tooltip text when collapsed. |
| iconreq | React.ElementType | - | Phosphor icon for the row. Required — the rail can always be collapsed, and a collapsed row is its glyph. |
| active | boolean | - | Current destination — accent glyph plus the trailing-edge marker. |
| onClick | () => void | - | Navigate handler. |
Sidebar
| Prop | Type | Default | Description |
|---|---|---|---|
| itemsreq | SidebarItem[] | - | The nav rows. The rail renders every row itself, which is what lets it guarantee that nothing mounts or reflows mid-fold. |
| footerItems | SidebarItem[] | [] | Utility rows (Docs, Settings) under their own hairline at the foot of the rail. They are destinations, so they are rows and not IconButtons, and they fold on the same switch as the nav above them. They carry their own marker scope, so an active footer row never pulls the marker out of the nav list. |
| logo | React.ReactNode | - | The mark at the top of the rail. Defaults to `AndromedaIcon` at 28px — behind `spacing[3]` that centres it on the rail's own 26px line at both widths. Size a replacement to the same box; `null` drops the mark. |
| title | React.ReactNode | - | ONE line of type beside the mark, naming the console. A rail that folds cannot afford a brand block whose height changes with the form, so this is a single line and never a two-line lockup. With no `title` and `logo={null}` the brand block and its hairline are not rendered at all. |
| collapsible | boolean | true | Renders the fold caret and lets the rail move between its two widths. False locks the rail at whichever width `defaultCollapsed` names and draws no caret: `collapsible={false}` is the static labelled sidebar, and `collapsible={false} defaultCollapsed` is the static icon rail. |
| defaultCollapsed | boolean | false | Which form the rail opens in. Expanded by default: that is the form the labels live in, and the rail folds down to icons on request. The rail owns this state; a page does not hold it. |
| onCollapsedChange | (collapsed: boolean) => void | - | Fired when the caret folds the rail. Notification only — the rail stays in charge of its own width, and this is here so a page can persist the reader's preference without taking ownership of it. |
| togglePlacement | 'footer'|'header' | 'footer' | Where the fold control lives. `footer` is the caret in its own block under its own seam at the foot of the rail. `header` is a 28px panel toggle (SidebarSimple, never turned) pinned 12px in from the brand block's right edge, which lands it on the mark's box at 52px. The mark fades out under it on the click that folds the rail and back in after the open. One element throughout, so focus stays on it. |
| children | React.ReactNode | - | Content under the nav rows, such as a chat history. Expanded form only: it fades with the labels and is inert while the rail is folded. It takes the rail's spare height and scrolls on its own, so the nav above and the footer below never move. Laid out at the expanded width, so nothing inside reflows mid-fold. |
| user | SidebarUser | - | The signed-in user's row at the foot of the rail under its own seam: avatar centred on the rail's line, name and role beside it fading with the labels, a chevron, and the account menu (`items`) opening upward. One row at both widths. |
| motionProps | import('framer-motion').MotionProps | - | Entrance choreography from a parent's `useCascadeProps` (foundations/motion.md). The root is already a motion element for the fold, so this rides on it. |
| className | string | - | Additional CSS classes applied to the root element. |
| style | React.CSSProperties | - | Inline styles applied to the root element. |