React AI Reasoning
Collapsible AI reasoning display with auto-streaming behavior. Build transparent AI interfaces with React, Next.js, and TypeScript, featuring automatic open/close and duration tracking for shadcn/ui applications.
Powered by
Trying to implement AI Elements?
Join our Discord community for help from other developers.
Collapsible reasoning display for AI models that show their thinking process in conversational AI applications. This free open source React component automatically opens during reasoning, closes when complete, and tracks thinking duration in Next.js projects.
Auto-collapsing reasoning display
Thinking indicator with expandable content:
Automatically opens during streaming in React applications, closes when complete in TypeScript components, tracks thinking duration, and provides smooth animations. Works with any reasoning-capable AI model in JavaScript frameworks.
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 {
Reasoning,
ReasoningTrigger,
ReasoningContent,
} from "@/components/ai/reasoning";
<Reasoning isStreaming={isThinking}>
<ReasoningTrigger title="Thinking" />
<ReasoningContent>Let me think about this step by step...</ReasoningContent>
</Reasoning>;
Why show AI reasoning?
Users don't trust black box responses for important decisions in React applications. Showing the thinking process builds confidence and lets users verify the logic in Next.js projects.
Duration tracking shows effort in TypeScript components. "Thought for 8 seconds" signals deliberate consideration, not instant pattern matching in JavaScript implementations.
Usage with Vercel AI SDK
Stream reasoning from models that support it using Vercel AI SDK in React applications:
"use client";
import {
Reasoning,
ReasoningTrigger,
ReasoningContent,
} from "@/components/ai/reasoning";
import {
Conversation,
ConversationContent,
} from "@/components/ai/conversation";
import { Message, MessageContent } from "@/components/ai/message";
import {
PromptInput,
PromptInputTextarea,
PromptInputSubmit,
} from "@/components/ai/prompt-input";
import { Response } from "@/components/ai/response";
import { useChat } from "@ai-sdk/react";
import { useState } from "react";
export default function ReasoningChat() {
const [input, setInput] = useState("");
const { messages, append, status } = useChat();
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (input.trim()) {
append({ role: "user", content: input });
setInput("");
}
};
return (
<div className="flex flex-col h-full max-w-4xl mx-auto">
<Conversation>
<ConversationContent>
{messages.map((message) => (
<Message from={message.role} key={message.id}>
<MessageContent>
{message.parts?.map((part, i) => {
switch (part.type) {
case "text":
return (
<Response key={`${message.id}-${i}`}>
{part.text}
</Response>
);
case "reasoning":
return (
<Reasoning
key={`${message.id}-${i}`}
isStreaming={status === "streaming"}
defaultOpen={false}
>
<ReasoningTrigger />
<ReasoningContent>{part.text}</ReasoningContent>
</Reasoning>
);
default:
return null;
}
})}
</MessageContent>
</Message>
))}
</ConversationContent>
</Conversation>
<PromptInput onSubmit={handleSubmit}>
<PromptInputTextarea
value={input}
onChange={(e) => setInput(e.currentTarget.value)}
placeholder="Ask me to reason through something..."
/>
<PromptInputSubmit disabled={!input.trim()} status={status} />
</PromptInput>
</div>
);
}
Backend route with reasoning support:
// app/api/chat/route.ts
import { streamText, convertToModelMessages } from "ai";
export async function POST(req: Request) {
const { messages } = await req.json();
const result = streamText({
model: "deepseek/deepseek-r1", // or other reasoning-capable model
messages: convertToModelMessages(messages),
});
return result.toUIMessageStreamResponse({
sendReasoning: true, // Enable reasoning part streaming
});
}
Features
- Automatic open/close behavior during reasoning streams (opens when reasoning starts, closes when done) in React applications
- Manual toggle control with smooth animations in TypeScript components
- Duration tracking with "Thought for X seconds" display for JavaScript frameworks
- Controllable state for custom behavior in Next.js projects
- Accessible keyboard navigation and screen reader support
- Works with any Vercel AI SDK setup and AI chat applications
- Free open source component designed for reasoning-capable AI models (DeepSeek R1, o1, etc.) in conversational AI interfaces
API Reference
Reasoning
Container component managing reasoning state and auto-behavior.
Prop | Type | Default | Description |
---|---|---|---|
isStreaming | boolean | false | Auto-opens when true, auto-closes when false |
open | boolean | - | Controlled open state |
defaultOpen | boolean | false | Initial open state for uncontrolled usage |
onOpenChange | (open: boolean) => void | - | Callback when open state changes |
duration | number | 0 | Controlled duration in seconds |
className | string | - | Additional CSS classes |
...props | ComponentProps<typeof Collapsible> | - | Collapsible component props |
ReasoningTrigger
Clickable trigger showing reasoning status and duration.
Prop | Type | Default | Description |
---|---|---|---|
title | string | "Reasoning" | Custom title for thinking state |
className | string | - | Additional CSS classes |
...props | ComponentProps<typeof CollapsibleTrigger> | - | Collapsible trigger props |
ReasoningContent
Content container for reasoning text with animations.
Prop | Type | Description |
---|---|---|
children | string | Required - Reasoning content text |
className | string | Additional CSS classes |
...props | ComponentProps<typeof CollapsibleContent> | Collapsible content props |
Keyboard interactions
Key | Description |
---|---|
Space / Enter | Toggle reasoning visibility on trigger |
Tab | Focus reasoning trigger |
Escape | Close reasoning panel when focused |
Reasoning display gotchas
Auto-close timing can feel abrupt: The React component auto-closes 1 second after streaming ends. Adjust AUTO_CLOSE_DELAY if users complain in TypeScript implementations.
Long reasoning breaks mobile: DeepSeek R1 reasoning can be 2000+ words in JavaScript applications. Set max-height and scroll, or mobile users scroll forever in Next.js projects.
Streaming performance issues: Large reasoning content updates rapidly in React components. Consider throttling updates for smoother animations.
Default open state matters: Most users want reasoning closed by default in TypeScript applications. They'll expand it if interested.
Empty reasoning handling: Not all models provide reasoning for every response in JavaScript frameworks. Handle undefined reasoning gracefully in React implementations.
Integration with other components
Works great with Response for formatted reasoning content in React applications. Drop into Message for chat-based reasoning display in Next.js projects. Combine with Conversation for scrolling reasoning streams. This free open source component integrates seamlessly with modern JavaScript frameworks.
Questions developers actually ask
React AI Prompt Input
Auto-resizing textarea with toolbar for chat interfaces. Build conversational UIs with React, Next.js, and TypeScript, featuring submit buttons, model selection, and keyboard shortcuts for shadcn/ui applications.
React AI Response
Streaming-optimized markdown renderer with syntax highlighting. Build rich AI content with React, Next.js, and TypeScript, featuring auto-completion of incomplete formatting and code blocks for shadcn/ui applications.