<!-- source-hash: eca198ef18bcc431169bc6caeb87161d -->
A sidebar component for chat navigation that displays a list of dialogs, supports infinite scroll pagination, and provides controls for creating new chats.

## Key Components

### `ChatSidebar`
The main container component that renders the sidebar with:
- **New Chat button** — triggers `onNewChat` callback
- **Dialog list** — scrollable list with infinite scroll via `IntersectionObserver`
- **Empty state** — shown when no dialogs exist and no `children` are provided
- **Custom content slot** — renders `children` instead of the dialog list when provided
- **Loading skeleton** — displays `ChatSidebarSkeleton` when `isLoading` is true and no dialogs are present

### `DialogListItem`
A single chat entry in the sidebar list. Displays:
- Chat title (truncated with tooltip)
- Formatted timestamp (`MM/DD/YYYY, HH:MM`)
- Unread message badge (capped at `99+`) or a chevron arrow when no unread messages exist
- Active state with accent border and background highlight

## Usage Example

```typescript
import { ChatSidebar } from "./chat-sidebar"

function App() {
  return (
    <ChatSidebar
      dialogs={[
        { id: "1", title: "Network Issue", timestamp: new Date(), unreadMessagesCount: 3 },
        { id: "2", title: "Server Setup", timestamp: new Date() },
      ]}
      activeDialogId="1"
      isLoading={false}
      isCreatingDialog={false}
      hasNextPage={true}
      isFetchingNextPage={false}
      onNewChat={() => console.log("New chat")}
      onDialogSelect={(id) => console.log("Selected:", id)}
      onLoadMore={() => fetchNextPage()}
    />
  )
}
```

## Infinite Scroll

Pagination is handled automatically using an `IntersectionObserver` anchored to the bottom of the scroll container. When the sentinel element enters the viewport and `hasNextPage` is `true`, `onLoadMore` is called. Skeleton items are shown while `isFetchingNextPage` is active.