logoassistant-ui

Reasoning

Overview

The Reasoning component displays AI reasoning or thinking messages in a collapsible UI. Consecutive reasoning message parts are automatically grouped together with smooth animations and a shimmer effect while streaming.

Getting Started

Add reasoning

npx assistant-ui@latest add reasoning
npx shadcn@latest add @assistant-ui/reasoning
npx shadcn@latest add "https://r.assistant-ui.com/reasoning"

This adds a /components/assistant-ui/reasoning.tsx file to your project, which you can adjust as needed.

Use in your application

Pass the Reasoning and ReasoningGroup components to the MessagePrimitive.Parts component:

/app/components/assistant-ui/thread.tsx
import { MessagePrimitive } from "@assistant-ui/react";
import { Reasoning, ReasoningGroup } from "@/components/assistant-ui/reasoning";

const AssistantMessage: FC = () => {
  return (
    <MessagePrimitive.Root className="...">
      <div className="...">
        <MessagePrimitive.Parts 
          components={{ 
            Reasoning: Reasoning,
            ReasoningGroup: ReasoningGroup
          }} 
        />
      </div>
      <AssistantActionBar />

      <BranchPicker className="..." />
    </MessagePrimitive.Root>
  );
};

How It Works

The component consists of two parts:

  1. Reasoning: Renders individual reasoning message part content
  2. ReasoningGroup: Wraps consecutive reasoning parts in a collapsible container

Consecutive reasoning parts are automatically grouped together by the ReasoningGroup component, similar to how ToolGroup handles tool calls.

Reasoning

The Reasoning component doesn't accept additional props—it renders the reasoning text content with markdown support.

Examples

Basic Usage

/app/components/assistant-ui/thread.tsx
<MessagePrimitive.Parts 
  components={{ 
    Reasoning,
    ReasoningGroup 
  }} 
/>

Custom Styling

Since the component is copied to your project, you can customize it directly by modifying the reasoning.tsx file. The internal components (ReasoningRoot, ReasoningTrigger, ReasoningContent, ReasoningText) accept className props for styling:

/components/assistant-ui/reasoning.tsx
const ReasoningGroupImpl: ReasoningGroupComponent = ({
  // ... existing code ...
  return (
    <ReasoningRoot className="rounded-lg border bg-muted/50 p-4">
      <ReasoningTrigger 
        active={isReasoningStreaming} 
        className="font-semibold text-foreground"
      />
      <ReasoningContent 
        aria-busy={isReasoningStreaming}
        className="mt-2"
      >
        <ReasoningText className="text-base">{children}</ReasoningText>
      </ReasoningContent>
    </ReasoningRoot>
  );
};

You can also customize the individual internal components:

/components/assistant-ui/reasoning.tsx
const ReasoningRoot: FC<PropsWithChildren<{ className?: string }>> = ({ 
  // ... existing code ...
  return (
    <Collapsible
      // ...
      className={cn("aui-reasoning-root mb-4 w-full rounded-lg border bg-muted/50 p-4", className)}
      // ...
    >
      {children}
    </Collapsible>
  );
};

const ReasoningTrigger: FC<{ active: boolean; className?: string }> = ({
  // ... existing code ...
  <CollapsibleTrigger
    className={cn(
      "aui-reasoning-trigger group/trigger -mb-2 flex max-w-[75%] items-center gap-2 py-2 text-sm font-semibold text-foreground transition-colors hover:text-foreground",
      className,
    )}
  >
    {/* ... existing content ... */}
  </CollapsibleTrigger>
);

Technical Details

Scroll Lock

The component uses the useScrollLock hook (exported from @assistant-ui/react) to prevent page jumps when collapsing the reasoning section. This maintains the scroll position during the collapse animation.

Animation Timing

The component uses CSS custom properties for animation timing:

  • --animation-duration: Controls expand/collapse animation (default: 200ms)
  • --shimmer-duration: Controls the shimmer effect speed (default: 1000ms)

These can be customized by modifying the CSS variables in your component.

  • ToolGroup - Similar grouping pattern for tool calls
  • PartGrouping - Experimental API for grouping message parts