# ThreadHistory
URL: /reference/react-ui-base/thread-history

import { ThreadHistoryDemoPreview } from "./_demos/thread-history-demo";

# ThreadHistory

`ThreadHistory` in `@tambo-ai/react-ui-base` owns thread collection state, search filtering, and selection behavior while keeping styling in `@tambo-ai/ui-registry` or your own UI layer.

## Demo

<ThreadHistoryDemoPreview />

## Anatomy

```tsx
<ThreadHistory.Root>
  <ThreadHistory.Search />
  <ThreadHistory.NewThreadButton />
  <ThreadHistory.List>
    <ThreadHistory.Item thread={thread} />
  </ThreadHistory.List>
</ThreadHistory.Root>
```

## Examples

### Active Thread Highlighting

Use the `data-active` attribute on `Item` to style the currently selected thread:

```tsx
<ThreadHistory.Item
  thread={thread}
  className="rounded px-2 py-1 data-active:bg-blue-100"
>
  {thread.id}
</ThreadHistory.Item>
```

### Thread Change Callback

Respond to thread switches and new thread creation:

```tsx
<ThreadHistory.Root onThreadChange={() => console.log("thread changed")}>
  {/* ... */}
</ThreadHistory.Root>
```

### Accessing List State via Render Props

Use the render prop on `List` to access filtered threads, loading, and error state:

```tsx
<ThreadHistory.List
  render={(props, state) => (
    <div {...props}>
      {state.isLoading && <p>Loading...</p>}
      {state.hasError && <p>Error: {state.error?.message}</p>}
      {state.isEmpty && <p>No threads found</p>}
      {state.filteredThreads.map((thread) => (
        <ThreadHistory.Item key={thread.id} thread={thread}>
          {thread.id}
        </ThreadHistory.Item>
      ))}
    </div>
  )}
/>
```

## API reference

### Root

| Prop             | Type         | Default     | Description                                                    |
| ---------------- | ------------ | ----------- | -------------------------------------------------------------- |
| `onThreadChange` | `() => void` | `undefined` | Callback invoked after a thread switch or new thread creation. |

**Render state:**

| Field            | Type      | Description                         |
| ---------------- | --------- | ----------------------------------- |
| `threadCount`    | `number`  | Count of filtered threads.          |
| `hasSearchQuery` | `boolean` | Whether a search query is active.   |
| `isLoading`      | `boolean` | Whether the thread list is loading. |

### Search

Renders as `<input type="text">`. No custom props. Reads and writes the search query from Root context.

**Render state:**

| Field         | Type     | Description           |
| ------------- | -------- | --------------------- |
| `searchQuery` | `string` | Current search query. |

### List

No custom props. Provides thread data and status through render state.

**Render state:**

| Field             | Type               | Description                             |
| ----------------- | ------------------ | --------------------------------------- |
| `isEmpty`         | `boolean`          | Whether filtered threads list is empty. |
| `isLoading`       | `boolean`          | Whether the thread list is loading.     |
| `hasError`        | `boolean`          | Whether an error occurred.              |
| `filteredThreads` | `ThreadListItem[]` | Array of search-filtered thread items.  |
| `searchQuery`     | `string`           | Current search query.                   |
| `error`           | `Error \| null`    | Error from thread list fetch.           |

### Item

| Prop     | Type             | Default  | Description                       |
| -------- | ---------------- | -------- | --------------------------------- |
| `thread` | `ThreadListItem` | Required | The thread to display and select. |

Renders as `<button>`. Sets `data-active` and `aria-current="true"` when the thread is the current active thread. When no children are provided, renders `thread.name` as the button label, falling back to `thread.id` if the name is empty or undefined.

**Render state:**

| Field      | Type             | Description                               |
| ---------- | ---------------- | ----------------------------------------- |
| `isActive` | `boolean`        | Whether this thread is the active thread. |
| `thread`   | `ThreadListItem` | The thread object.                        |

### NewThreadButton

No custom props. Renders as `<button>`. Calls `startNewThread()`, `refetch()`, and `onThreadChange()` on click.

**Render state:**

| Field  | Type     | Description              |
| ------ | -------- | ------------------------ |
| `slot` | `string` | The component slot name. |

## Accessibility

* `Item` renders as a `<button>` with `aria-current="true"` on the active thread for screen-reader accessibility.
* `Search` renders as an `<input>` with `aria-label="Search threads"` built in.
* `NewThreadButton` renders as a `<button>`.

## Styling Hooks

* `data-slot="thread-history"`
* `data-slot="thread-history-search"`
* `data-slot="thread-history-list"`
* `data-slot="thread-history-item"`
* `data-slot="thread-history-new-thread-button"`
* `data-active` on `Item` when thread is active
* `aria-current="true"` on `Item` when thread is active
