# Navigator

## Introduction

The Navigator component is a sidebar navigation system that renders hierarchical navigation menus. It combines NavigationItem and NavigationGroup components to create expandable, nested navigation structures commonly found in admin dashboards and complex applications. Navigator automatically handles indentation levels and provides a consistent visual hierarchy for multi-level navigation.

```text
// Unable to derive source for Playground
```

| Field                        | Description | Default |
| ---------------------------- | ----------- | ------- |
| Controls resolved at runtime | —           | —       |

## Usage

```tsx
import { Navigator } from '@ceed/cds';

function Sidebar() {
  const items = [
    { id: 'home', type: 'item', title: 'Home', startDecorator: <HomeIcon /> },
    {
      type: 'group',
      title: 'Projects',
      startDecorator: <FolderIcon />,
      content: (
        <Navigator
          items={[
            { id: 'project-a', type: 'item', title: 'Project A' },
            { id: 'project-b', type: 'item', title: 'Project B' },
          ]}
          level={1}
          onSelect={handleSelect}
        />
      ),
    },
  ];

  return <Navigator items={items} onSelect={handleSelect} />;
}
```

## Examples

### Basic Navigation

A simple navigation with items and a collapsible group.

```text
// Unable to derive source for Playground
```

### Default Expanded

Groups can be expanded by default using the `expanded` property.

```text
// Unable to derive source for DefaultExpanded
```

## When to Use

### ✅ Good Use Cases

- **Admin dashboards**: Sidebar navigation for complex admin interfaces
- **Nested content structures**: When content has hierarchical relationships
- **Multi-section applications**: Apps with distinct modules or feature areas
- **File/folder structures**: Representing folder hierarchies in file managers
- **Settings pages**: Organizing settings into categories and subcategories

### ❌ When Not to Use

- **Primary navigation bars**: Use horizontal navigation or tabs instead
- **Simple sites**: Sites with fewer than 5 navigation items don't need hierarchy
- **Mobile-first layouts**: Consider drawer navigation or bottom tabs instead
- **Flat navigation**: When all items are at the same level, use simple list
- **Wizard/step flows**: Use Stepper for sequential processes

## Common Use Cases

### Admin Dashboard Sidebar

```tsx
function AdminSidebar() {
  const [selectedId, setSelectedId] = useState('dashboard');

  const items = [
    {
      id: 'dashboard',
      type: 'item',
      title: 'Dashboard',
      startDecorator: <DashboardIcon />,
      selected: selectedId === 'dashboard',
    },
    {
      type: 'group',
      title: 'User Management',
      startDecorator: <PeopleIcon />,
      content: (
        <Navigator
          level={1}
          onSelect={setSelectedId}
          items={[
            { id: 'users', type: 'item', title: 'All Users', selected: selectedId === 'users' },
            { id: 'roles', type: 'item', title: 'Roles', selected: selectedId === 'roles' },
            { id: 'permissions', type: 'item', title: 'Permissions', selected: selectedId === 'permissions' },
          ]}
        />
      ),
    },
    {
      type: 'group',
      title: 'Settings',
      startDecorator: <SettingsIcon />,
      content: (
        <Navigator
          level={1}
          onSelect={setSelectedId}
          items={[
            { id: 'general', type: 'item', title: 'General', selected: selectedId === 'general' },
            { id: 'security', type: 'item', title: 'Security', selected: selectedId === 'security' },
          ]}
        />
      ),
    },
  ];

  return <Navigator items={items} onSelect={setSelectedId} />;
}
```

### File Browser Navigation

```tsx
function FileBrowser({ folders, onFolderSelect }) {
  const buildNavigatorItems = (folderList, level = 0) => {
    return folderList.map((folder) => {
      if (folder.children && folder.children.length > 0) {
        return {
          type: 'group',
          title: folder.name,
          startDecorator: <FolderIcon />,
          expanded: folder.expanded,
          content: (
            <Navigator
              level={level + 1}
              items={buildNavigatorItems(folder.children, level + 1)}
              onSelect={onFolderSelect}
            />
          ),
        };
      }
      return {
        id: folder.id,
        type: 'item',
        title: folder.name,
        startDecorator: <FolderIcon />,
        selected: folder.selected,
      };
    });
  };

  return (
    <Navigator
      items={buildNavigatorItems(folders)}
      onSelect={onFolderSelect}
    />
  );
}
```

### Multi-level Documentation Navigation

```tsx
function DocsNavigation({ sections, currentPath }) {
  const items = sections.map((section) => ({
    type: 'group',
    title: section.title,
    startDecorator: <ArticleIcon />,
    expanded: currentPath.startsWith(section.path),
    content: (
      <Navigator
        level={1}
        onSelect={navigateTo}
        items={section.pages.map((page) => ({
          id: page.path,
          type: 'item',
          title: page.title,
          selected: currentPath === page.path,
        }))}
      />
    ),
  }));

  return <Navigator items={items} onSelect={navigateTo} />;
}
```

## Component Structure

Navigator uses a composition pattern with NavigationItem and NavigationGroup:

```tsx
<Navigator>
  {/* Renders internally: */}
  <NavigationItem>       {/* For type: 'item' */}
  <NavigationGroup>      {/* For type: 'group' */}
    {content}            {/* Usually another Navigator for nesting */}
  </NavigationGroup>
</Navigator>
```

## Props and Customization

### Navigator Props

| Prop       | Type                                  | Default | Description                       |
| ---------- | ------------------------------------- | ------- | --------------------------------- |
| `items`    | `(NavigatorItem \| NavigatorGroup)[]` | `[]`    | Array of navigation items         |
| `level`    | `number`                              | `0`     | Nesting level for indentation     |
| `onSelect` | `(id: string) => void`                | -       | Callback when an item is selected |

### Navigator Item Type

```tsx
interface NavigatorItem {
  id: string;                        // Unique identifier
  type: 'item';                      // Indicates a navigation item
  title: string | React.ReactNode;   // Display text or element
  startDecorator?: React.ReactNode;  // Icon before title
  selected?: boolean;                // Selection state
}
```

### Navigator Group Type

```tsx
interface NavigatorGroup {
  type: 'group';                     // Indicates a group
  title: string | React.ReactNode;   // Group title
  startDecorator?: React.ReactNode;  // Icon before title
  expanded?: boolean;                // Default expanded state
  content: React.ReactNode;          // Content when expanded (usually nested Navigator)
}
```

### Nested Navigation Pattern

```tsx
// Create nested navigation by passing higher level values
<Navigator
  level={0}  // Root level
  items={[
    {
      type: 'group',
      title: 'Section',
      content: (
        <Navigator
          level={1}  // First nesting level
          items={[...]}
          onSelect={handleSelect}
        />
      ),
    },
  ]}
  onSelect={handleSelect}
/>
```

## Accessibility

Navigator components follow accessibility best practices:

### ARIA Attributes

- NavigationItem uses `aria-current` for the selected item
- NavigationGroup uses accordion ARIA patterns for expand/collapse
- Proper focus management within navigation

### Keyboard Navigation

- **Tab**: Move focus through navigation items
- **Enter/Space**: Select item or toggle group
- **Arrow Up/Down**: Navigate between items (when accordion is focused)

### Screen Reader Support

```tsx
// Items are announced with their selection state
<NavigationItem selected={true}>
  Dashboard {/* Announced as current page */}
</NavigationItem>

// Groups announce their expanded state
<NavigationGroup expanded={true}>
  Settings {/* Announced as expanded */}
</NavigationGroup>
```

## Best Practices

### ✅ Do

1. **Use icons consistently**: Either use icons for all items or none

```tsx
// ✅ Good: Consistent icons
const items = [
  { id: 'home', type: 'item', title: 'Home', startDecorator: <HomeIcon /> },
  { id: 'settings', type: 'item', title: 'Settings', startDecorator: <SettingsIcon /> },
];

// ❌ Bad: Inconsistent icons
const items = [
  { id: 'home', type: 'item', title: 'Home', startDecorator: <HomeIcon /> },
  { id: 'settings', type: 'item', title: 'Settings' },  // Missing icon
];
```

2. **Manage selection state in parent**: Keep track of selected item at the top level

```tsx
function Sidebar() {
  const [selectedId, setSelectedId] = useState('home');

  // Pass selected state down through items
  const items = buildItems(selectedId);

  return <Navigator items={items} onSelect={setSelectedId} />;
}
```

3. **Pass onSelect to nested Navigators**: Ensure child navigators also receive the callback

4. **Limit nesting depth**: 2-3 levels maximum for usability

### ❌ Don't

1. **Don't over-nest**: Deep nesting makes navigation confusing

```tsx
// ❌ Bad: Too many levels
<Navigator level={0}>
  <Navigator level={1}>
    <Navigator level={2}>
      <Navigator level={3}>  {/* Too deep */}
```

2. **Don't mix navigation patterns**: Stick to either all items or items with groups

3. **Don't use for actions**: Navigator is for navigation, not for triggering actions

## Performance Considerations

### Memoize Items Array

When items are computed, memoize them to prevent unnecessary re-renders:

```tsx
const items = useMemo(() => [
  {
    id: 'home',
    type: 'item',
    title: 'Home',
    selected: currentPath === '/home',
  },
  // ... more items
], [currentPath]);

<Navigator items={items} onSelect={handleSelect} />
```

### Lazy Load Content

For groups with heavy content, consider lazy loading:

```tsx
const item = {
  type: 'group',
  title: 'Reports',
  content: expanded ? <ReportsList /> : null,
};
```

### Virtual Scrolling

For very long navigation lists, consider implementing virtual scrolling or pagination.

Navigator provides a flexible foundation for building hierarchical navigation systems. Use it alongside NavigationItem and NavigationGroup for maximum control, or let Navigator handle the rendering automatically based on your items array.
