# BranchPicker
URL: /docs/primitives/branch-picker

Navigate between message branches, which are alternative responses the user can flip through.

The BranchPicker primitive lets users navigate between message branches, which are alternative responses generated by editing a message or regenerating a reply. It's used alongside ActionBar inside message components.

<Tabs items="[&#x22;Preview&#x22;, &#x22;Code&#x22;]">
  <Tab>
    <BranchPickerPrimitiveSample />
  </Tab>

  <Tab>
    ```tsx
    import {
      BranchPickerPrimitive,
      MessagePrimitive,
    } from "@assistant-ui/react";
    import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react";

    function AssistantMessage() {
      return (
        <MessagePrimitive.Root className="flex flex-col items-start gap-1">
          <div className="rounded-2xl bg-muted px-4 py-2.5 text-sm">
            <MessagePrimitive.Parts />
          </div>
          <BranchPickerPrimitive.Root className="inline-flex items-center gap-0.5 text-xs">
            <BranchPickerPrimitive.Previous className="flex size-6 items-center justify-center rounded-md disabled:opacity-30">
              <ChevronLeftIcon className="size-3.5" />
            </BranchPickerPrimitive.Previous>
            <span>
              <BranchPickerPrimitive.Number /> / <BranchPickerPrimitive.Count />
            </span>
            <BranchPickerPrimitive.Next className="flex size-6 items-center justify-center rounded-md disabled:opacity-30">
              <ChevronRightIcon className="size-3.5" />
            </BranchPickerPrimitive.Next>
          </BranchPickerPrimitive.Root>
        </MessagePrimitive.Root>
      );
    }
    ```
  </Tab>
</Tabs>

Quick Start \[#quick-start]

Minimal example:

```tsx
import { BranchPickerPrimitive } from "@assistant-ui/react";

<BranchPickerPrimitive.Root>
  <BranchPickerPrimitive.Previous>←</BranchPickerPrimitive.Previous>
  <BranchPickerPrimitive.Number /> / <BranchPickerPrimitive.Count />
  <BranchPickerPrimitive.Next>→</BranchPickerPrimitive.Next>
</BranchPickerPrimitive.Root>
```

`Root` renders a `<div>`, `Previous` and `Next` render `<button>` elements that auto-disable at boundaries. `Number` and `Count` render plain text (the current branch index and total count).

<Callout type="info">
  BranchPicker must be placed inside a `MessagePrimitive.Root` because it reads branch state from the nearest message context.
</Callout>

<Callout type="info">
  Runtime setup: primitives require runtime context. Wrap your UI in `AssistantRuntimeProvider` with a runtime (for example `useLocalRuntime(...)`). See [Pick a Runtime](/docs/runtimes/pick-a-runtime).
</Callout>

Core Concepts \[#core-concepts]

Branch Navigation \[#branch-navigation]

`Previous` and `Next` buttons automatically disable at boundaries. `Previous` is disabled on the first branch, and `Next` is disabled on the last. Both also disable while the thread is running if the runtime doesn't support `switchBranchDuringRun`.

Number & Count \[#number--count]

`Number` and `Count` are text-only primitives that render raw numbers with no wrapping element. Use a `<span>` if you need to style them:

```tsx
<span className="tabular-nums">
  <BranchPickerPrimitive.Number /> / <BranchPickerPrimitive.Count />
</span>
```

hideWhenSingleBranch \[#hidewhensinglebranch]

The `hideWhenSingleBranch` prop on `Root` hides the entire picker when there's only one branch. This is a common production pattern to reduce visual clutter:

```tsx
<BranchPickerPrimitive.Root hideWhenSingleBranch>
  <BranchPickerPrimitive.Previous>←</BranchPickerPrimitive.Previous>
  <BranchPickerPrimitive.Number /> / <BranchPickerPrimitive.Count />
  <BranchPickerPrimitive.Next>→</BranchPickerPrimitive.Next>
</BranchPickerPrimitive.Root>
```

Context Requirement \[#context-requirement]

BranchPicker reads branch state from the nearest message context. It must be placed inside a `MessagePrimitive.Root`, either directly or nested inside your message component.

Parts \[#parts]

Root \[#root]

Container with optional `hideWhenSingleBranch`. Renders a `<div>` element unless `asChild` is set.

```tsx
<BranchPickerPrimitive.Root hideWhenSingleBranch className="inline-flex items-center gap-1">
  <BranchPickerPrimitive.Previous>←</BranchPickerPrimitive.Previous>
  <BranchPickerPrimitive.Number /> / <BranchPickerPrimitive.Count />
  <BranchPickerPrimitive.Next>→</BranchPickerPrimitive.Next>
</BranchPickerPrimitive.Root>
```

<PrimitivesTypeTable type="BranchPickerPrimitiveRootProps" parameters="BranchPickerPrimitiveDocs.Root.props.filter(p => p.name !== &#x22;asChild&#x22;)" />

Previous \[#previous]

Button that selects the previous branch. Renders a `<button>` element unless `asChild` is set.

```tsx
<BranchPickerPrimitive.Previous>Previous</BranchPickerPrimitive.Previous>
```

Next \[#next]

Button that selects the next branch. Renders a `<button>` element unless `asChild` is set.

```tsx
<BranchPickerPrimitive.Next>Next</BranchPickerPrimitive.Next>
```

Number \[#number]

Displays the current branch number.

```tsx
<BranchPickerPrimitive.Number />
```

Count \[#count]

Displays the total number of branches for the current message.

```tsx
<BranchPickerPrimitive.Count />
```

Patterns \[#patterns]

Standard Picker with Icons \[#standard-picker-with-icons]

```tsx
import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react";

<BranchPickerPrimitive.Root
  hideWhenSingleBranch
  className="inline-flex items-center gap-1 text-xs text-muted-foreground"
>
  <BranchPickerPrimitive.Previous className="size-6 rounded-md hover:bg-muted disabled:opacity-30">
    <ChevronLeftIcon className="size-3.5" />
  </BranchPickerPrimitive.Previous>
  <span className="tabular-nums">
    <BranchPickerPrimitive.Number /> / <BranchPickerPrimitive.Count />
  </span>
  <BranchPickerPrimitive.Next className="size-6 rounded-md hover:bg-muted disabled:opacity-30">
    <ChevronRightIcon className="size-3.5" />
  </BranchPickerPrimitive.Next>
</BranchPickerPrimitive.Root>
```

Custom Elements with asChild \[#custom-elements-with-aschild]

```tsx
<BranchPickerPrimitive.Previous asChild>
  <MyIconButton tooltip="Previous branch">
    <ChevronLeftIcon />
  </MyIconButton>
</BranchPickerPrimitive.Previous>
```

The primitive's disabled state and click handler merge onto your element.

Inside a Message Footer \[#inside-a-message-footer]

The most common pattern places the BranchPicker alongside an ActionBar in a message footer:

```tsx
function AssistantMessage() {
  return (
    <MessagePrimitive.Root>
      <div className="rounded-xl bg-muted p-3">
        <MessagePrimitive.Parts />
      </div>
      <div className="flex items-center justify-between">
        <BranchPickerPrimitive.Root hideWhenSingleBranch>
          {/* prev / number / count / next */}
        </BranchPickerPrimitive.Root>
        <ActionBarPrimitive.Root>
          <ActionBarPrimitive.Copy>Copy</ActionBarPrimitive.Copy>
          <ActionBarPrimitive.Reload>Reload</ActionBarPrimitive.Reload>
        </ActionBarPrimitive.Root>
      </div>
    </MessagePrimitive.Root>
  );
}
```

Relationship to Components \[#relationship-to-components]

The shadcn [Thread](/docs/ui/thread) component includes a BranchPicker in both AssistantMessage and UserMessage footers, with `hideWhenSingleBranch` enabled. If the default layout works, use the component. Reach for `BranchPickerPrimitive` directly when you need a custom position, different styling, or a non-standard branch navigation experience.

API Reference \[#api-reference]

For full prop details on every part, see the [BranchPickerPrimitive API Reference](/docs/api-reference/primitives/branch-picker).

Related:

* [ActionBarPrimitive API Reference](/docs/api-reference/primitives/action-bar)
* [MessagePrimitive API Reference](/docs/api-reference/primitives/message)
