Chat Interface
Using the AI chat component and useAIChat hook.
Chat Interface
The AI chat interface provides a conversational experience powered by Vercel AI SDK v6.
useAIChat Hook
The useAIChat hook manages all chat state and interactions.
Basic Usage
import { useAIChat } from '@/components/ai';
function ChatPage() {
const {
messages,
input,
setInput,
sendMessage,
isLoading,
error,
clearMessages,
} = useAIChat();
return (
<div>
{messages.map((msg) => (
<div key={msg.id}>
<strong>{msg.role}:</strong> {msg.content}
</div>
))}
<input
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyDown={(e) => e.key === 'Enter' && sendMessage()}
/>
<button onClick={() => sendMessage()} disabled={isLoading}>
Send
</button>
</div>
);
}
Options
const chat = useAIChat({
// Custom API endpoint
endpoint: '/api/ai/chat',
// Initial messages
initialMessages: [
{ id: '1', role: 'assistant', content: 'Hello!' }
],
// Callbacks
onSend: (message) => console.log('Sent:', message),
onResponse: (message) => console.log('Response:', message),
onError: (error) => console.error('Error:', error),
});
Return Values
| Property | Type | Description |
|---|---|---|
messages | UIMessage[] | All messages in conversation |
input | string | Current input value |
setInput | (value: string) => void | Set input value |
sendMessage | (content?: string) => Promise<void> | Send a message |
status | ChatStatus | Current status |
isLoading | boolean | Whether loading |
error | Error | null | Current error |
clearMessages | () => void | Clear all messages |
regenerate | () => Promise<void> | Regenerate last response |
stop | () => void | Stop current generation |
approveToolCall | (id: string) => void | Approve a tool |
rejectToolCall | (id: string) => void | Reject a tool |
ChatContainer Component
Pre-built container with input, messages, and status display.
import { ChatContainer, useAIChat } from '@/components/ai';
function ChatPage() {
const chat = useAIChat();
return (
<ChatContainer
messages={chat.messages}
input={chat.input}
onInputChange={chat.setInput}
onSend={chat.sendMessage}
status={chat.status}
isLoading={chat.isLoading}
error={chat.error?.message}
onToolApprove={chat.approveToolCall}
onToolReject={chat.rejectToolCall}
title="AI Assistant"
placeholder="Ask me anything..."
emptyContent={{
icon: 'π€',
title: 'Welcome!',
description: 'How can I help you today?',
}}
/>
);
}
Props
| Prop | Type | Default | Description |
|---|---|---|---|
messages | UIMessage[] | Required | Messages to display |
input | string | '' | Current input value |
onInputChange | (value: string) => void | - | Input change handler |
onSend | (message: string) => void | - | Send handler |
status | ChatStatus | 'idle' | Current status |
isLoading | boolean | false | Loading state |
error | string | - | Error message |
title | string | 'AI Assistant' | Header title |
showHeader | boolean | true | Show header |
placeholder | string | 'Type a message...' | Input placeholder |
ChatMessage Component
Renders individual messages with support for parts (text, tool calls, results).
import { ChatMessage } from '@/components/ai';
<ChatMessage
message={message}
userAvatar="π€"
assistantAvatar="π€"
showTimestamp
onToolApprove={(id) => console.log('Approved:', id)}
onToolReject={(id) => console.log('Rejected:', id)}
/>
Message Structure
Messages can contain multiple parts:
interface UIMessage {
id: string;
role: 'user' | 'assistant' | 'system';
content: string;
createdAt?: Date;
parts?: UIMessagePart[];
}
type UIMessagePart =
| { type: 'text'; text: string }
| { type: 'tool-call'; toolCallId: string; toolName: string; args: object }
| { type: 'tool-result'; toolCallId: string; result: unknown }
| { type: 'reasoning'; reasoning: string }
| { type: 'source'; source: { title?: string; url: string } };
Streaming Responses
The chat automatically handles streaming:
- User sends message
- Status changes to
'submitted' - API call initiated
- Status changes to
'streaming' - Message content updates in real-time
- Status returns to
'idle'
// Visual feedback during streaming
{chat.status === 'streaming' && (
<div>AI is typing...</div>
)}