File: reasoning.md | Updated: 11/15/2025
Slash Forward
Docs Cookbook Providers Playground AI ElementsAI ElementsLeft sparkleRight sparkle AI GatewayGateway
Search...⌘KFeedback GitHub Vercel LogoSign in with Vercel
Chatbot
A collapsible component that displays AI reasoning content, automatically opening during streaming and closing when finished.
The Reasoning component displays AI reasoning content, automatically opening during streaming and closing when finished.
Preview
Code
Thought for a few seconds
AI Elements
shadcn CLI
Manual
npx ai-elements@latest add reasoning
Build a chatbot with reasoning using Deepseek R1.
Add the following component to your frontend:
app/page.tsx
'use client';
import {
Reasoning,
ReasoningContent,
ReasoningTrigger,
} from '@/components/ai-elements/reasoning';
import {
Conversation,
ConversationContent,
ConversationScrollButton,
} from '@/components/ai-elements/conversation';
import {
PromptInput,
PromptInputTextarea,
PromptInputSubmit,
} from '@/components/ai-elements/prompt-input';
import { Loader } from '@/components/ai-elements/loader';
import { Message, MessageContent, MessageResponse } from '@/components/ai-elements/message';
import { useState } from 'react';
import { useChat } from '@ai-sdk/react';
const ReasoningDemo = () => {
const [input, setInput] = useState('');
const { messages, sendMessage, status } = useChat();
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
sendMessage({ text: input });
setInput('');
};
return (
<div className="max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]">
<div className="flex flex-col h-full">
<Conversation>
<ConversationContent>
{messages.map((message) => (
<Message from={message.role} key={message.id}>
<MessageContent>
{message.parts.map((part, i) => {
switch (part.type) {
case 'text':
return (
<MessageResponse key={`${message.id}-${i}`}>
{part.text}
</MessageResponse>
);
case 'reasoning':
return (
<Reasoning
key={`${message.id}-${i}`}
className="w-full"
isStreaming={status === 'streaming' && i === message.parts.length - 1 && message.id === messages.at(-1)?.id}
>
<ReasoningTrigger />
<ReasoningContent>{part.text}</ReasoningContent>
</Reasoning>
);
}
})}
</MessageContent>
</Message>
))}
{status === 'submitted' && <Loader />}
</ConversationContent>
<ConversationScrollButton />
</Conversation>
<PromptInput
onSubmit={handleSubmit}
className="mt-4 w-full max-w-2xl mx-auto relative"
>
<PromptInputTextarea
value={input}
placeholder="Say something..."
onChange={(e) => setInput(e.currentTarget.value)}
className="pr-12"
/>
<PromptInputSubmit
status={status === 'streaming' ? 'streaming' : 'ready'}
disabled={!input.trim()}
className="absolute bottom-1 right-1"
/>
</PromptInput>
</div>
</div>
);
};
export default ReasoningDemo;
Add the following route to your backend:
app/api/chat/route.ts
import { streamText, UIMessage, convertToModelMessages } from 'ai';
// Allow streaming responses up to 30 seconds
export const maxDuration = 30;
export async function POST(req: Request) {
const { model, messages }: { messages: UIMessage[]; model: string } =
await req.json();
const result = streamText({
model: 'deepseek/deepseek-r1',
messages: convertToModelMessages(messages),
});
return result.toUIMessageStreamResponse({
sendReasoning: true,
});
}
<Reasoning />Prop
Type
isStreaming?boolean
...props?React.ComponentProps<typeof Collapsible>
<ReasoningTrigger />Prop
Type
title?string
...props?React.ComponentProps<typeof CollapsibleTrigger>
<ReasoningContent />Prop
Type
...props?React.ComponentProps<typeof CollapsibleContent>
Queue
A comprehensive queue component system for displaying message lists, todos, and collapsible task sections in AI applications.
Shimmer
An animated text shimmer component for creating eye-catching loading states and progressive reveal effects.
On this page
Installation
Usage with AI SDK
Features
Props
<Reasoning />
<ReasoningTrigger />
<ReasoningContent />
GitHubEdit this page on GitHub Scroll to topCopy pageOpen in chat