## App Sidebar (S—489)

A floating app sidebar: search that filters the nav, badges, nested groups, a sliding marker and an icon rail.

- URL: https://sundaeui.dev/components/app-sidebar
- Category: Navigation & menus · Art direction: Refined
- Access: Sundae Pro (authenticated install)
- Stack: React 18+, TypeScript, plain CSS; dependencies: none
- Install: `npx shadcn@latest add https://sundaeui.dev/r/app-sidebar.json`
- Tags: dashboard, sidebar, rail, command, saas, search, app-shell, collapse, menu, navigation

The whole left side of an app in one component. A workspace header, a search row that turns into a field (⌘K) and filters every item in place with arrow-key results, sections with headings, counts and unread dots, groups that fold open, a footer with settings and help, and a user row that opens an account menu.
The current page is marked by a raised pill that slides between rows rather than jumping. Collapse it (button or [) and the panel narrows to a 60px rail: icons stay exactly where they were while labels, badges and headings blur away, and hovering or focusing an icon shows its name in a tooltip. In the rail, the logo turns into the expand button on hover.
Navigation is links when you pass href, so middle-click and ⌘-click still open new tabs; pass onNavigate to route in-app. It can be controlled or left to manage its own state.

### Usage

```tsx
import { AppSidebar } from '@/components/sundae/app-sidebar'

<div style={{ display: 'flex', height: '100dvh', padding: 12, gap: 12 }}>
  <AppSidebar
    workspace={{ name: 'Northwind', plan: 'Team plan' }}
    sections={[
      { id: 'main', items: [
        { id: 'home', label: 'Home', icon: 'home', href: '/' },
        { id: 'inbox', label: 'Inbox', icon: 'inbox', href: '/inbox', badge: 12 },
      ] },
      { id: 'work', label: 'Workspace', items: [
        { id: 'projects', label: 'Projects', icon: 'folder', children: [
          { id: 'web', label: 'Website relaunch', href: '/p/web' },
        ] },
      ] },
    ]}
    footer={[{ id: 'settings', label: 'Settings', icon: 'settings', href: '/settings' }]}
    user={{ name: 'Ada Lovelace', email: 'ada@northwind.co' }}
    activeId={current}
    onNavigate={(item) => router.push(item.href!)}
    onUserAction={(id) => id === 'sign-out' && signOut()}
  />
  <main style={{ flex: 1 }}>{children}</main>
</div>
```

### Props

- `workspace` (`{ name, plan?, initials?, color? }`, required): Header. Initials come from the name unless given.
- `sections` (`SidebarSection[]`, required): { id, label?, items }. Items are { id, label, icon?, href?, badge?, children? }.
- `footer` (`SidebarItem[]`): Rows pinned above the user, e.g. Settings and Help.
- `user / userActions` (`{ name, email?, initials? } / { id, label, danger? }[]`): Account row and its menu. Defaults to Profile, Settings, Sign out.
- `activeId` (`string`): The current page. Its group opens and the marker slides to it.
- `onNavigate` (`(item) => void`): Called on click or Enter in search. Without it, rows with href are plain links.
- `onUserAction` (`(id: string) => void`): Called with the chosen account action.
- `notice / onDismissNotice` (`{ id, title, body?, action? }`): A dismissible card above the footer; hidden in the rail.
- `collapsed / defaultCollapsed / onCollapsedChange` (`boolean`, default `false`): Controlled or uncontrolled rail state.
- `searchShortcut` (`string | null`, default `'k'`): Opens search with ⌘ or Ctrl. null turns it off.
- `collapseShortcut` (`string | null`, default `'['`): Toggles the rail when no field has focus.
- `icon` (`SidebarIconName | ReactNode`): 16 built-in icons (home, inbox, folder, chart, …) or your own 16px node.
- `theme` (`'auto' | 'light' | 'dark'`, default `'auto'`): auto follows a .dark ancestor.

### When to use

- The main navigation of a dashboard or SaaS app.
- Apps with enough pages that search and collapsible groups help.

### When not to use

- A marketing site header: use a top nav.
- A short list of tabs within one page: use Tabs.

### Accessibility

- Each section is a labelled nav; the current row has aria-current="page".
- Groups are buttons with aria-expanded and aria-controls; closed groups are inert.
- Search is a combobox: arrow keys move through results (aria-activedescendant), Enter opens, Escape closes and returns focus.
- In the rail every row keeps an accessible name, and tooltips appear on keyboard focus as well as hover.
- The account menu uses role="menu": focus moves into it, arrows/Home/End move, Escape closes and returns focus.
- Reduced motion removes the slide, blur and fold animations.
