Join our Discord Community

React AI Branch

Navigate between multiple AI response variations. Build interactive chat experiences with React, Next.js, and TypeScript, featuring branch navigation and version control for shadcn/ui applications.

Trying to implement AI Elements?

Join our Discord community for help from other developers.


Users want to compare different AI responses without losing the good ones. This builds branching into your chat UI so they can navigate between variations instead of refreshing and hoping for better luck.

Response branching

Navigate between different AI response variations:

Loading component...

Handles branch state without Redux ceremony in React applications, uses CSS transitions so switching doesn't feel janky, and aligns navigation controls properly. Complete TypeScript definitions that actually make sense.

Installation

npx shadcn@latest add https://www.shadcn.io/registry/ai.json
npx shadcn@latest add https://www.shadcn.io/registry/ai.json
pnpm dlx shadcn@latest add https://www.shadcn.io/registry/ai.json
bunx shadcn@latest add https://www.shadcn.io/registry/ai.json

Usage

import {
  Branch,
  BranchMessages,
  BranchNext,
  BranchPage,
  BranchPrevious,
  BranchSelector,
} from "@/components/ai/branch";

<Branch defaultBranch={0}>
  <BranchMessages>
    <Message from="user">
      <MessageContent>Hello</MessageContent>
    </Message>
    <Message from="user">
      <MessageContent>Hi!</MessageContent>
    </Message>
  </BranchMessages>
  <BranchSelector from="user">
    <BranchPrevious />
    <BranchPage />
    <BranchNext />
  </BranchSelector>
</Branch>;

Why not just use a state library?

Most developers reach for Zustand or Redux for branch management in React applications. That's overkill. This React component handles the state you actually need—current branch index and navigation—without the ceremony.

Users don't get perfect responses on the first try in Next.js applications. They want to see alternatives without losing what's already good. Before this free open source component, they'd copy-paste responses into notes apps like animals.

Usage with Vercel AI SDK

Vercel AI SDK focuses on streaming and generation—it doesn't handle response variations in JavaScript applications. That's where this TypeScript component fits in. You manage the array of responses, we handle the UI for React applications:

"use client";

import {
  Branch,
  BranchMessages,
  BranchSelector,
  BranchPrevious,
  BranchPage,
  BranchNext,
} from "@/components/ai/branch";
import { Message, MessageContent } from "@/components/ai/message";
import { useState } from "react";

export default function Chat() {
  const [responses, setResponses] = useState<string[]>([]);
  const [currentBranch, setCurrentBranch] = useState(0);

  const generateVariation = async () => {
    // Your AI generation logic
    const newResponse = await generateResponse();
    setResponses([...responses, newResponse]);
  };

  return (
    <Branch defaultBranch={currentBranch} onBranchChange={setCurrentBranch}>
      <BranchMessages>
        {responses.map((response, index) => (
          <Message from="assistant" key={index}>
            <MessageContent>{response}</MessageContent>
          </Message>
        ))}
      </BranchMessages>
      {responses.length > 1 && (
        <BranchSelector from="assistant">
          <BranchPrevious />
          <BranchPage />
          <BranchNext />
        </BranchSelector>
      )}
    </Branch>
  );
}

Features

  • Branch state management that doesn't require a PhD in React applications
  • Navigation controls that work on mobile (not tiny buttons) in Next.js projects
  • CSS transitions instead of re-rendering everything for JavaScript performance
  • Shows "2 of 5" so users know where they are in TypeScript applications
  • Keyboard navigation that doesn't break accessibility
  • Works with any Vercel AI SDK setup in React frameworks
  • Free open source component designed for conversational AI interfaces

API Reference

Branch

Container managing branch state and navigation.

PropTypeDefaultDescription
defaultBranchnumber0Index of the branch to show by default
onBranchChange(index: number) => void-Callback when branch changes
...propsHTMLAttributes<HTMLDivElement>-HTML attributes for root div

BranchMessages

Container for branch message variations.

PropTypeDescription
...propsHTMLAttributes<HTMLDivElement>HTML attributes for root div

BranchSelector

Navigation control container with alignment.

PropTypeDescription
fromUIMessage["role"]Aligns selector for user/assistant/system
...propsHTMLAttributes<HTMLDivElement>HTML attributes for container

BranchPrevious / BranchNext

Navigation buttons for branch control.

PropTypeDescription
...propsComponentProps<Button>Spreads to underlying Button component

BranchPage

Branch position indicator.

PropTypeDescription
...propsHTMLAttributes<HTMLSpanElement>HTML attributes for span element

Keyboard interactions

KeyDescription
TabMove focus to navigation controls
Enter / SpaceActivate focused navigation button
ArrowLeftPrevious branch (when focused)
ArrowRightNext branch (when focused)

Things that will bite you

Branch state gets lost on refresh: Store in localStorage if users care about persistence in React applications. Most don't for casual conversations.

Users click through branches too fast: Add a small transition delay or they'll think switching is broken in Next.js projects.

Memory leaks with too many branches: Limit to 5-7 branches and auto-prune old ones in JavaScript applications. Nobody needs 20 variations.

Showing navigation with only one branch: Hide the controls when there's nothing to navigate in TypeScript components. It just confuses people.

Auto-generating variations: Never do this automatically in React applications. Users want control over when you spend their tokens.

Integration with other components

Works great with Message components for displaying the actual content in React applications. Add Actions to each branch for copy/regenerate buttons in Next.js projects. This free open source component family is designed to work together in modern JavaScript frameworks.

Questions developers actually ask