# Sidebar

## Overview

The `Sidebar` is the primary vertical navigation panel of the application shell. It manages the app's hierarchy, supporting simple lists, grouped items, and an advanced "Assistant" mode for AI-driven or data-rich interfaces.

It is a responsive component that can be expanded or collapsed as an icon-only strip, fully integrated with the `LayoutContext` for state management.

The component ships with **three usage patterns** to cover different levels of customization:

| Pattern                                                        | When to use                                               |
| -------------------------------------------------------------- | --------------------------------------------------------- |
| **Monolithic API** (`<Sidebar />`)                             | Standard usage — pass props, get a fully-featured sidebar |
| **Compound Component API** (`<Sidebar.Root>` + sub-components) | Custom layouts — compose only the parts you need          |
| **Headless Hook** (`useSidebar()`)                             | Full control — manage state yourself, render anything     |

---

## Variants

### 1. Default

A clean, structured navigation list for standard dashboards and settings areas.

- Supports a flat `routes` list OR grouped navigation via `navigationGroups`.
- Each route can have `children` — sub-routes exposed via a contextual `ChevronRight` button at the end of the item.

### 2. Assistant (Advanced)

Designed for complex tools, agents, or multi-context navigation.

- **Search**: Built-in search bar with optional advanced filtering.
- **Groups**: Support for sections with labels, descriptions, and action menus.
- **Fixed Areas**: Pinned top container for persistent actions (like "New Conversation").

---

## When to Use

- Use it to host the primary navigation routes of your platform.
- Choose `variant="assistant"` when building tools that require local search or frequent creation of new items (e.g., GPT-style interfaces).

---

## Props

### `<Sidebar />` (Monolithic API)

| Prop               | Type                       | Default                                   | Description                                                                             |
| ------------------ | -------------------------- | ----------------------------------------- | --------------------------------------------------------------------------------------- |
| `expanded`         | `boolean`                  | `auto`                                    | Controlled state. Defaults to `LayoutContext` or local state.                           |
| `onToggle`         | `() => void`               | `auto`                                    | Toggle callback. Defaults to `LayoutContext` or local state.                            |
| `variant`          | `'default' \| 'assistant'` | `'default'`                               | Controls the internal layout and features.                                              |
| `routes`           | `RouteConfig[]`            | —                                         | Flat navigation items (default variant, no groups).                                     |
| `navigationGroups` | `RouteGroup[]`             | —                                         | Grouped navigation items with labels. Works in both `default` and `assistant` variants. |
| `fixedArea`        | `SidebarFixedAreaConfig`   | —                                         | Pinned top button (assistant variant — e.g. "New Conversation").                        |
| `search`           | `SidebarSearchConfig`      | —                                         | Search bar configuration (assistant variant).                                           |
| `logo`             | `ReactNode`                | —                                         | Logo shown when expanded.                                                               |
| `logoCollapsed`    | `ReactNode`                | —                                         | Logo shown when collapsed.                                                              |
| `width`            | `number`                   | `280`                                     | Expanded sidebar width in pixels.                                                       |
| `footer`           | `SidebarFooterConfig`      | —                                         | Footer visibility flags (`showUser`, `showSettings`, `showLogout`).                     |
| `showFooter`       | `boolean`                  | `true` for default, `false` for assistant | Whether to render the footer section.                                                   |

### `<Sidebar.Root />` (Compound Component)

| Prop       | Type                     | Default                | Description                                                                          |
| ---------- | ------------------------ | ---------------------- | ------------------------------------------------------------------------------------ |
| `expanded` | `boolean`                | `auto`                 | Controlled expansion state.                                                          |
| `onToggle` | `() => void`             | `auto`                 | Toggle callback.                                                                     |
| `navigate` | `(path: string) => void` | `window.location.href` | Navigation handler.                                                                  |
| `location` | `{ pathname: string }`   | `window.location`      | Current location for active state.                                                   |
| `width`    | `number`                 | `280`                  | Expanded width in pixels.                                                            |
| `children` | `ReactNode`              | —                      | Sub-components: `Sidebar.Header`, `Sidebar.Nav`, `Sidebar.Footer`, `Sidebar.Search`. |

### `useSidebar()` (Headless Hook)

```ts
import { useSidebar } from 'xertica-ui/layout';

const {
  expanded, // boolean — current expansion state
  setExpanded, // (value: boolean | fn) => void
  toggleExpanded, // () => void
  isMobileViewport, // boolean
  hasOverflow, // boolean — nav items overflow the container
  visibleItems, // RouteGroup[] — items that fit in the nav
  overflowItems, // RouteGroup[] — items that overflow
  openSubmenu, // string | null
  setOpenSubmenu, // (id: string | null) => void
  isFilterOpen, // boolean
  setIsFilterOpen, // (open: boolean) => void
  navRef, // RefObject<HTMLElement> — attach to nav container
  navigationGroups, // RouteGroup[] — the resolved groups passed in
} = useSidebar({
  defaultExpanded: true,
  navigationGroups: myGroups,
});
```

### RouteConfig

| Field         | Type               | Description                                                          |
| ------------- | ------------------ | -------------------------------------------------------------------- |
| `path`        | `string`           | Navigation path                                                      |
| `label`       | `string`           | Display label                                                        |
| `icon`        | `ComponentType`    | Leading icon component                                               |
| `children`    | `RouteConfig[]`    | Sub-routes. **Desktop**: ChevronRight opens a lateral DropdownMenu. **Mobile**: ChevronRight toggles an inline accordion below the parent item. |
| `actions`     | `ActionMenuItem[]` | Contextual action menu items (ellipsis button — assistant variant)   |
| `description` | `ReactNode`        | Auxiliary content shown when the route is active (assistant variant) |

### RouteGroup

| Field     | Type               | Description                       |
| --------- | ------------------ | --------------------------------- |
| `id`      | `string`           | Unique identifier                 |
| `label`   | `string`           | Group title                       |
| `icon`    | `ComponentType`    | Group icon                        |
| `items`   | `RouteConfig[]`    | Navigation items in the group     |
| `actions` | `ActionMenuItem[]` | Context menu for the entire group |

---

## Examples

### 1. Monolithic API — Flat Routes

```tsx
import { Sidebar } from 'xertica-ui/layout';
import { useLayout } from 'xertica-ui/hooks';
import { useLocation, useNavigate } from 'react-router-dom';
import { Home, Settings } from 'lucide-react';

export function MySidebar() {
  const { sidebarExpanded, toggleSidebar, sidebarWidth } = useLayout();
  const location = useLocation();
  const navigate = useNavigate();

  return (
    <Sidebar
      expanded={sidebarExpanded}
      onToggle={toggleSidebar}
      width={sidebarWidth}
      location={location}
      navigate={navigate}
      routes={[
        { path: '/', label: 'Home', icon: Home },
        { path: '/settings', label: 'Settings', icon: Settings },
      ]}
    />
  );
}
```

### 2. Monolithic API — Groups with Children

```tsx
import { BarChart, Users, Settings, Home } from 'lucide-react';

<Sidebar
  navigationGroups={[
    {
      id: 'main',
      label: 'Principal',
      items: [
        { path: '/home', label: 'Início', icon: Home },
        {
          path: '/dashboard',
          label: 'Dashboard',
          icon: BarChart,
          children: [
            { path: '/dashboard/overview', label: 'Visão Geral' },
            { path: '/dashboard/reports', label: 'Relatórios' },
          ],
        },
      ],
    },
    {
      id: 'admin',
      label: 'Administração',
      items: [
        { path: '/users', label: 'Usuários', icon: Users },
        { path: '/settings', label: 'Configurações', icon: Settings },
      ],
    },
  ]}
/>;
```

### 3. Compound Component API

Use this when you need to inject custom content between sections or reorder the layout:

```tsx
import { Sidebar } from 'xertica-ui/layout';
import { Home, BarChart } from 'lucide-react';

export function CustomSidebar({ expanded, onToggle }) {
  return (
    <Sidebar.Root
      expanded={expanded}
      onToggle={onToggle}
      width={280}
      location={{ pathname: window.location.pathname }}
      navigate={path => (window.location.href = path)}
    >
      {/* Toggle button + logo */}
      <Sidebar.Header logo={<MyLogo />} logoCollapsed={<MyIcon />} />

      {/* Custom content injected between header and nav */}
      <div className="px-4 py-2">
        <span className="text-xs text-sidebar-foreground/60">v2.0.0</span>
      </div>

      {/* Navigation */}
      <Sidebar.Nav
        navigationGroups={[
          {
            id: 'main',
            items: [
              { path: '/home', label: 'Home', icon: Home },
              { path: '/dashboard', label: 'Dashboard', icon: BarChart },
            ],
          },
        ]}
      />

      {/* Footer */}
      <Sidebar.Footer
        user={{ name: 'Admin', email: 'admin@example.com' }}
        onLogout={() => signOut()}
        showUser
        showSettings
        showLogout
      />
    </Sidebar.Root>
  );
}
```

### 4. Headless Hook — Fully Custom UI

Use `useSidebar` when you need complete control over the rendered output:

```tsx
import { useSidebar } from 'xertica-ui/layout';
import { Home, BarChart } from 'lucide-react';

const groups = [
  {
    id: 'main',
    items: [
      { path: '/home', label: 'Home', icon: Home },
      { path: '/dashboard', label: 'Dashboard', icon: BarChart },
    ],
  },
];

export function MyCustomSidebar() {
  const { expanded, toggleExpanded, navigationGroups } = useSidebar({
    defaultExpanded: true,
    navigationGroups: groups,
  });

  return (
    <aside style={{ width: expanded ? 280 : 80 }}>
      <button onClick={toggleExpanded}>Toggle</button>
      <nav>
        {navigationGroups
          .flatMap(g => g.items)
          .map(item => (
            <a key={item.path} href={item.path}>
              {expanded ? item.label : null}
            </a>
          ))}
      </nav>
    </aside>
  );
}
```

---

## Accessibility (v2.1.9+)

The `default` variant sidebar ships with the following ARIA enhancements:

| Element       | Attribute       | Value                   | Description                         |
| ------------- | --------------- | ----------------------- | ----------------------------------- |
| Toggle button | `aria-expanded` | `{expanded}`            | Signals open/closed state to AT     |
| Toggle button | `aria-controls` | `"sidebar-nav"`         | Links button to the nav it controls |
| `<nav>`       | `id`            | `"sidebar-nav"`         | Target of `aria-controls`           |
| `<nav>`       | `aria-label`    | `"Navegação principal"` | Identifies the nav landmark         |

These attributes are applied automatically — no consumer configuration needed.

---

## AI Rules

- **State Management** — Always use `useLayout()` to keep the Sidebar synchronized with the main content padding. Avoid managing `expanded` locally unless using the Headless Hook pattern.
- **Icons** — Pass the icon **component source** (e.g., `HomeIcon`), not a rendered element.
- **Groups** — Use `navigationGroups` in `default` variant for structured navigation with labels. Use `routes` for flat lists.
- **Children (sub-items)** — Add `children` to a `RouteConfig` to expose sub-routes. On **desktop** (≥ 768 px), a ChevronRight button opens a lateral `DropdownMenu` positioned to the right of the sidebar. On **mobile** (< 768 px), the same button toggles an **inline accordion** that expands the child items directly below the parent, with a rotation animation on the ChevronRight icon. Do not nest more than 2 levels.
- **Assistant Mode** — Use `fixedArea` to place high-priority "Create" buttons so they remain visible regardless of scrolling.
- **Compound Components** — Use `<Sidebar.Root>` + sub-components when you need to inject custom content between sections or reorder the layout.
- **Headless Hook** — Use `useSidebar()` only when you need a completely custom sidebar UI that shares none of the default rendering.
- **location prop** — Always pass `location={useLocation()}` from `react-router-dom` when using inside a Router. Passing a stale `window.location` reference prevents active-state updates on navigation.

---

## Storybook Stories

| Story name                  | Description                                                                             |
| --------------------------- | --------------------------------------------------------------------------------------- |
| `Default`                   | Flat routes, collapsed sidebar.                                                         |
| `DefaultWithGroups`         | Groups with `children` sub-items — desktop dropdown behavior.                           |
| `Assistant`                 | Assistant variant with search, filter, fixedArea, and nested action menus.              |
| `Collapsed`                 | Sidebar in collapsed icon-only mode.                                                    |
| `NoFooter`                  | `showFooter={false}`.                                                                   |
| `Autonomous`                | No `expanded`/`onToggle` props — fully internal state.                                  |
| `WithSubitemsDesktop`       | Sidebar expanded with sub-items visible. Click ChevronRight to open the lateral dropdown. |
| `WithSubitemsMobile`        | Simulates a 375 px viewport. Open the sidebar via the hamburger button to see sub-items expand inline as an accordion. |
| `CompoundComponentAPI`      | `<Sidebar.Root>` + `<Sidebar.Header>` + `<Sidebar.Nav>` + `<Sidebar.Footer>`.          |
| `HeadlessHook`              | Fully custom UI via `useSidebar()`.                                                     |

---

## Related Components

- [`Header`](./header.md) — Responsible for the mobile sidebar trigger.
- [`useLayout`](../layout.md) — The context provider managing sidebar state.
