# Sidebar

> Persistent left navigation cho admin/dashboard — hỗ trợ icon-only collapse, nested items với expand/collapse.

**Archetype mapping:** A (Dashboard) · B (Tool) — primary nav cho admin/SaaS layout.

## API

| Prop | Type | Default | Description |
|---|---|---|---|
| `brand` | `ReactNode` | — | Logo/brand top sidebar (ẩn khi collapsed) |
| `items` | `SidebarItem[]` | required | Cây nav |
| `collapsible` | `boolean` | `true` | Bật nút collapse (chuyển sang icon-only) |
| `defaultCollapsed` | `boolean` | `false` | State mở/đóng mặc định |
| `className` | `string` | — | Override aside |

### `SidebarItem` (recursive)

| Field | Type | Description |
|---|---|---|
| `label` | `string` | Text item |
| `href` | `string?` | URL — render `<a>` (chỉ khi không có `items` nested) |
| `icon` | `ReactNode?` | Icon trái |
| `active` | `boolean?` | Highlight current item (bg-primary-soft) |
| `items` | `SidebarItem[]?` | Children → render group header với expand/collapse |

## Variants

2 cấp item:
- **Leaf** (có `href`, không `items`) — render `<a>` link
- **Group** (có `items`) — render `<button>` toggle, children indent với border-left

State collapse:
- **Expanded** (w-64): hiện full label + icon
- **Collapsed** (w-16): chỉ icon, label ẩn, group children không render (collapsed = không nested expand)

## Composition

Recursive — `SidebarNode` render lại chính nó cho children. Group children cap level 2 không hardcode nhưng UI chỉ test 2 cấp.

## States

- **Default leaf**: text-text-2 hover → text-text + bg-surface-2
- **Active leaf**: bg-primary-soft + text-primary-deep + font-medium
- **Group header**: text-text-3 uppercase tracking-wider — visual differentiation từ leaf
- **Group expanded**: children visible với border-left indent
- **Group collapsed**: children hidden, chevron `rotate-90` → vertical
- **Sidebar collapsed**: w-16, group items hidden (chỉ icon visible)

## Usage

```tsx
import { Sidebar } from '@cowork/ui';

<Sidebar
  brand={<span>An Nhiên Admin</span>}
  items={[
    { label: 'Dashboard', href: '/', icon: <HomeIcon />, active: true },
    {
      label: 'Bán hàng',
      icon: <CartIcon />,
      items: [
        { label: 'Đơn hàng', href: '/orders' },
        { label: 'Khách hàng', href: '/customers' },
        { label: 'Sản phẩm', href: '/products' },
      ],
    },
    {
      label: 'Marketing',
      icon: <MegaphoneIcon />,
      items: [
        { label: 'Campaigns', href: '/marketing/campaigns' },
        { label: 'Content', href: '/marketing/content' },
      ],
    },
    { label: 'Settings', href: '/settings', icon: <SettingsIcon /> },
  ]}
  defaultCollapsed={false}
/>
```

## Real-world example

- An Nhien admin (`tools.dang.pm` style): Sidebar với groups [Dashboard · Bán hàng (Orders/Customers/Products) · Marketing (Campaigns/Content) · Settings].
- KHI CRM: Sidebar với groups [Members (Trial/Active/Churn) · Bookings (Schedule/Past) · Analytics (Revenue/Funnel) · Settings].
- Internal AI tools dashboard: Sidebar groups [Projects · Sources (Pancake/Supabase/n8n) · Tasks · Logs].

## Accessibility

- `<aside>` element native — landmark cho screen reader
- Active item có `aria-current="page"`
- Collapsed leaf có `title={label}` (tooltip native browser) để screen reader/hover đọc full label
- Group toggle có `aria-expanded`
- Collapse button có `aria-label="Expand/Collapse sidebar"`

## Responsive behavior

- Width animate `transition-all duration-base` giữa w-16 và w-64
- **Không tự collapse mobile** — caller responsibility:
  - Pattern phổ biến: mobile dùng [[Drawer]] thay vì Sidebar persistent
  - Hoặc set `defaultCollapsed={true}` cho viewport <md
- Sidebar luôn `flex-col` height full → caller wrap trong layout `flex h-screen`:
  ```tsx
  <div className="flex h-screen">
    <Sidebar items={…} />
    <main className="flex-1 overflow-auto">…</main>
  </div>
  ```

## Related

- [[Navbar]] — top nav mỏng, complement với Sidebar trong admin layout
- [[Drawer]] — mobile alternative cho Sidebar (temporary slide từ left)
- [[Breadcrumb]] — đặt trong main content area để show vị trí dưới navigation

## Source

`react/src/organisms/Sidebar.tsx`
