# Sidebar

- Page: <https://kznlabs.github.io/labsUI/components/sidebar>

## Sidebar (`sidebar`, component)

App navigation from data: header, groups (optionally foldable), badges and pinned footer entries. Collapses to an icon rail on a spring (⌘B / Ctrl+B) with labels kept for assistive tech; below md it is a left drawer.

- Install: `npx @kznlabs/labsui add sidebar`
- Docs: <https://kznlabs.github.io/labsUI/components/sidebar>
- Brings: button, button-variants, collapsible, dialog, drawer, platform, use-controllable-state, use-hotkey, utils
- npm: clsx@^2.1.1, lucide-react@1.63.0, motion@14.7.1, tailwind-merge@^3.7.0

### API

- `<SidebarLayout>` (+ <div> props): Lays the sidebar and the page side by side and holds the rail state. Below md, the sidebar is a left drawer.
  - `collapsed?: boolean`: Controlled rail state; pair with `onCollapsedChange`.
  - `defaultCollapsed?: boolean` = `false`: Start as the icon rail (uncontrolled).
  - `onCollapsedChange?: (collapsed: boolean) => void`: Called from the trigger or the shortcut.
  - `shortcut?: boolean` = `true`: Toggle with ⌘B / Ctrl+B (default: true). Ignored while typing in a field.
- `<Sidebar>`: Navigation sidebar from data. Collapses to an icon rail on a spring; labels clip but stay in the a11y tree.
  - `groups: SidebarGroup[]`: The navigation, top to bottom.
  - `current?: string`: Id of the current item: highlighted, `aria-current="page"` on links.
  - `footer?: SidebarItem[]`: Entries pinned to the bottom, e.g. settings.
  - `header?: ReactNode`: Top slot, e.g. the workspace name.
  - `label?: string` = `"Sidebar"`: Accessible name for the navigation landmark.
  - `onSelect?: (id: string) => void`: Called with an item's id when it is picked (links too, e.g. for client routing).
- `<SidebarTrigger>`

- `type SidebarItem = { id?: string; label: string; icon?: ReactNode; href?: string; badge?: ReactNode; }`
- `type SidebarGroup = { label?: string; items: SidebarItem[]; collapsible?: boolean; defaultOpen?: boolean; }`

### Usage

```tsx
<SidebarLayout><Sidebar groups={[{ label: "Server", items: [{ label: "Home", href: "/", icon: <Home /> }] }]} current="/" /><main><SidebarTrigger />…</main></SidebarLayout>
```

### Example: admin-layout.tsx

```tsx
"use client";

import { Home, Inbox, Settings } from "lucide-react";
import { usePathname } from "next/navigation";
import { Sidebar, SidebarLayout, SidebarTrigger } from "@/components/ui/sidebar";

const groups = [
  {
    label: "Server",
    items: [
      { label: "Overview", href: "/", icon: <Home /> },
      { label: "Inbox", href: "/inbox", icon: <Inbox />, badge: 12 },
    ],
  },
];

export function AdminLayout({ children }: { children: React.ReactNode }) {
  return (
    <SidebarLayout className="h-dvh">
      <Sidebar
        label="Admin"
        groups={groups}
        footer={[{ label: "Settings", href: "/settings", icon: <Settings /> }]}
        current={usePathname()}
      />
      <main className="min-w-0 flex-1">
        <SidebarTrigger />
        {children}
      </main>
    </SidebarLayout>
  );
}
```
