# Sidebar Section Layout: Top/Bottom Positioning & Scrollable Sections

## Summary

Extend `Sidebar.Section` with two new optional props:

- `position: 'top' | 'bottom'` — controls whether a section stacks from the top of the sidebar or from the bottom (above the footer). Default: `'top'`.
- `maxHeight: string` — CSS length value (e.g. `"250px"`, `"30vh"`) that constrains the section's content area. When content exceeds this height, it scrolls. The section header/toggle always remains visible.

This enables a layout where primary sections (Applications, Agents) occupy the top of the sidebar, while secondary sections (Routes, Starred) cluster near the bottom — with a flexible spacer absorbing remaining vertical space between the two groups.

## API Changes

### `Sidebar.Section` — new optional props

```tsx
interface SidebarSectionProps {
  icon: ReactNode
  label: string
  open: boolean
  onToggle: () => void
  active?: boolean
  children: ReactNode
  className?: string
  position?: 'top' | 'bottom'  // default: 'top'
  maxHeight?: string            // CSS length, e.g. "250px", "30vh"
}
```

No changes to `Sidebar.Header`, `Sidebar.Footer`, `Sidebar.FooterLink`, or `SidebarRoot` props.

### Consumer usage

```tsx
<Sidebar>
  <Sidebar.Header ... />

  <Sidebar.Section label="Applications" ...>
    <SidebarTree ... />
  </Sidebar.Section>

  <Sidebar.Section label="Agents" ...>
    <SidebarTree ... />
  </Sidebar.Section>

  <Sidebar.Section label="Routes" position="bottom" maxHeight="200px" ...>
    <SidebarTree ... />
  </Sidebar.Section>

  <Sidebar.Section label="Starred" position="bottom" ...>
    ...
  </Sidebar.Section>

  <Sidebar.Footer>...</Sidebar.Footer>
</Sidebar>
```

## Layout Model

### SidebarRoot child partitioning

`SidebarRoot` already inspects children to extract `Header`. This extends the same pattern:

1. Extract `Header` children (existing)
2. Extract `Footer` children
3. Partition remaining children into `topSections` and `bottomSections` based on `position` prop (default `'top'`)

### Render structure

```
<aside class="sidebar">
  [collapse toggle]
  {header}
  {search bar}
  <div class="sectionGroup sectionGroupTop">
    {topSections}
  </div>
  <div class="sectionSpacer" />
  <div class="sectionGroup sectionGroupBottom">
    {bottomSections}
  </div>
  {footer}
</aside>
```

When there are no bottom sections, the spacer is omitted. The layout behaves identically to today — footer's `margin-top: auto` handles positioning. Zero breaking changes for existing consumers.

### SidebarSection content wrapper

A new `.sectionContent` div wraps only the `children` inside `SidebarSection` (not the toggle header). When `maxHeight` is provided, it receives the value as an inline `max-height` style.

```tsx
{open && (
  <div
    className={styles.sectionContent}
    style={maxHeight ? { maxHeight } : undefined}
  >
    {children}
  </div>
)}
```

## CSS Changes

### Group wrappers

```css
.sectionGroup {
  flex: 0 1 auto;
  overflow-y: auto;
  min-height: 0;
}

.sectionSpacer {
  flex: 1 0 0;
}
```

### Section content scrolling

```css
.sectionContent {
  overflow-y: auto;
}
```

`maxHeight` is applied as an inline style, not a CSS class, since it varies per section instance.

### Custom scrollbars

Applied to both `.sectionGroup` and `.sectionContent` to keep the dark sidebar aesthetic:

```css
/* Standard (Firefox, modern Chrome/Edge) */
scrollbar-width: thin;
scrollbar-color: rgba(255, 255, 255, 0.15) transparent;

/* WebKit (Safari, older Chrome) */
::-webkit-scrollbar {
  width: 4px;
}

::-webkit-scrollbar-track {
  background: transparent;
}

::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.15);
  border-radius: 2px;
}

::-webkit-scrollbar-thumb:hover {
  background: rgba(255, 255, 255, 0.3);
}
```

## Collapsed Sidebar Behavior

In collapsed (icon rail) mode, sections render as single icon buttons with no scrollable content:

- **`position`**: Respected — bottom sections render in the bottom group, so their icons cluster near the footer in the rail.
- **`maxHeight`**: Ignored — no content to constrain.

The group wrapper and spacer structure remains active in collapsed mode for consistent icon positioning.

## Edge Cases

| Scenario | Behavior |
|----------|----------|
| All sections `"top"` (no bottom sections) | No spacer rendered. Identical to current layout. |
| All sections `"bottom"` | Top group empty. Sections cluster above footer. |
| `maxHeight` set but content is shorter | No visual effect — wrapper is naturally smaller than max. |
| Very short viewport | Both group wrappers scroll independently via `overflow-y: auto` on `.sectionGroup`. |

## Files Changed

- `src/design-system/layout/Sidebar/Sidebar.tsx` — add `position` and `maxHeight` props to `SidebarSectionProps`, add `sectionContent` wrapper to `SidebarSection`, partition children in `SidebarRoot`
- `src/design-system/layout/Sidebar/Sidebar.module.css` — add `.sectionGroup`, `.sectionSpacer`, `.sectionContent`, custom scrollbar styles
- `src/design-system/layout/Sidebar/Sidebar.test.tsx` — new test cases for positioning and scrolling behavior

## Tests

- Section with `maxHeight` renders content wrapper with correct inline style and `overflow-y: auto`
- Sections with `position="bottom"` render inside the bottom group wrapper
- Default `position` (omitted) renders in the top group
- When no bottom sections exist, no spacer is rendered
- Collapsed sidebar renders bottom sections in the bottom group
