Sidebar
The app shell's navigation: collapsible, with groups, badges and an active item.
When to use
- The main navigation of an app: sources, records, conversations, settings.
- An app with more sections than fit in a top bar, grouped under labels.
When not to use
- Site navigation with a few top-level sections: use Navigation Menu.
- A trail back up the hierarchy: use Breadcrumb.
- Filters or details beside the content: use Sheet.
Install
npx shadcn@latest add @clinia/sidebarClinia rules
- Exactly one item is
isActive: the current page. It gets abg-sidebar-accent/15tint andfont-medium, with foreground text. - Hover is the ink tint,
bg-sidebar-foreground/4, so a hovered item never reads as the current page. - Item labels are short nouns that match the page title:
Sources, notManage your sources. - Counts sit in
SidebarMenuBadge. When the sidebar collapses to icons, give eachSidebarMenuButtonatooltipwith its label.
Do and don't
States
Toggle the site theme to review both themes.
Sizes
| Size | Height | Padding x | Gap | Radius | Type |
|---|---|---|---|---|---|
| default | h-9 · 36px | px-3 · 12px | gap-2 · 8px | --radius-md | text-sm · 14px |
| sm | h-8 · 32px | px-3 · 12px | gap-2 · 8px | --radius-md | text-xs · 12px |
| lg | h-14 · 56px | px-3 · 12px | gap-2 · 8px | --radius-md | text-sm · 14px |
Accessibility
Built in
- The active item is tinted
bg-sidebar-accent/15with foreground text: Trust never sits behind label-size text.isActivealso setsdata-activefor your own styling. - Cmd+B on macOS or Ctrl+B elsewhere toggles the sidebar.
- On mobile it opens as a Sheet, which moves focus inside and returns it on close.
SidebarTriggerandSidebarRailare labelled buttons, so they are named for screen readers.
Your responsibility
isActivestyles the item but doesn't setaria-current. Passaria-current="page"on the active item yourself.- Render items that navigate as links:
render={<Link href="/sources" />}onSidebarMenuButton. - Put the page content in
SidebarInset, which renders<main>, and wrap the menu in<nav aria-label="Workspace">.
How to test
- Press Tab through the items: each one shows the Trust focus ring.
- With a screen reader, the active item is announced as
Sources, current page, link. - Press Cmd+B or Ctrl+B: the sidebar collapses, and Cmd+B again restores it.
- At a mobile width, open the sidebar: focus moves inside it. Press Escape: it closes and focus returns to the trigger.
API
Sidebar
| Prop | Values | Default | Description |
|---|---|---|---|
| side | leftright | left | Which edge of the screen the sidebar sits on. |
| variant | sidebarfloatinginset | sidebar |
|
| collapsible | offcanvasiconnone | offcanvas |
|
SidebarMenuAction
| Prop | Values | Default | Description |
|---|---|---|---|
| showOnHover | boolean | false | Hides the action until its row is hovered or focused. |
SidebarMenuButton
| Prop | Values | Default | Description |
|---|---|---|---|
| isActive | boolean | false | Marks the current page. Sets |
| tooltip | string | (TooltipPopupProps & Pick<TooltipPositionerProps, "align" | "alignOffset" | "side" | "sideOffset">) | – | Label shown on hover when the sidebar is collapsed to icons. |
| variant | defaultoutline | default |
|
| size | defaultsmlg | default | Height: |
SidebarMenuSkeleton
| Prop | Values | Default | Description |
|---|---|---|---|
| showIcon | boolean | false | Adds an icon placeholder to the skeleton row. |
SidebarMenuSubButton
| Prop | Values | Default | Description |
|---|---|---|---|
| size | smmd | md | Text size of the nested item. |
| isActive | boolean | false | Marks the current page. Sets |
SidebarProvider
| Prop | Values | Default | Description |
|---|---|---|---|
| defaultOpen | boolean | true | Whether the sidebar starts expanded. |
| open | boolean | – | Controlled expanded state. Pair with |
| onOpenChange | ((open: boolean) => void) | – | Called when the user expands or collapses the sidebar. |
All other props come from the native div element.