Loading...
Loading...
shadcn/ui AI chat components for conversational interfaces. Use for streaming chat, tool/function displays, reasoning visualization, or encountering Next.js App Router setup, Tailwind v4 integration, AI SDK v5 migration errors.
npx skill4agent add secondsky/claude-skills ai-elements-chatbotpnpm dlx ai-elements@latest initpnpm dlx ai-elements@latest add message conversation response prompt-input'use client';
import { useChat } from 'ai/react';
import { Conversation } from '@/components/ui/ai/conversation';
import { Message } from '@/components/ui/ai/message';
import { Response } from '@/components/ui/ai/response';
import { PromptInput } from '@/components/ui/ai/prompt-input';
export default function ChatPage() {
const { messages, input, handleInputChange, handleSubmit } = useChat({
api: '/api/chat'
});
return (
<div className="flex h-screen flex-col">
<Conversation>
{messages.map((msg) => (
<Message key={msg.id} role={msg.role}>
<Response markdown={msg.content} />
</Message>
))}
</Conversation>
<PromptInput
value={input}
onChange={handleInputChange}
onSubmit={handleSubmit}
/>
</div>
);
}references/setup-guide.mdimport { Conversation } from '@/components/ui/ai/conversation';
import { Message } from '@/components/ui/ai/message';
<Conversation>
{messages.map((msg) => (
<Message key={msg.id} role={msg.role}>
{msg.content}
</Message>
))}
</Conversation>import { Response } from '@/components/ui/ai/response';
<Response markdown={content} />import { PromptInput } from '@/components/ui/ai/prompt-input';
<PromptInput
value={input}
onChange={handleInputChange}
onSubmit={handleSubmit}
/>import { CodeBlock } from '@/components/ui/ai/code-block';
<CodeBlock code={code} language="typescript" />import { Reasoning } from '@/components/ui/ai/reasoning';
<Reasoning content={thinking} />import { Tool } from '@/components/ui/ai/tool';
<Tool name="search" args={{ query: "..." }} result={result} />pnpm dlx ai-elements@latestconst { messages, input, handleInputChange, handleSubmit } = useChat();
return (
<>
<Conversation>
{messages.map(m => (
<Message key={m.id} role={m.role}>
<Response markdown={m.content} />
</Message>
))}
</Conversation>
<PromptInput value={input} onChange={handleInputChange} onSubmit={handleSubmit} />
</>
);{messages.map(m => (
<Message key={m.id} role={m.role}>
{m.toolInvocations?.map(tool => (
<Tool key={tool.toolCallId} name={tool.toolName} args={tool.args} result={tool.result} />
))}
<Response markdown={m.content} />
</Message>
))}<Message role="assistant">
{reasoning && <Reasoning content={reasoning} />}
<Response markdown={content} />
</Message><Response markdown={content}>
{(node) => node.type === 'code' ? (
<CodeBlock code={node.value} language={node.lang} />
) : null}
</Response><Message role="assistant">
<Response markdown={content} />
<Sources sources={sources} />
</Message>// app/api/chat/route.ts
import { streamText } from 'ai';
import { openai } from '@ai-sdk/openai';
export async function POST(req: Request) {
const { messages } = await req.json();
const result = streamText({
model: openai('gpt-4'),
messages
});
return result.toDataStreamResponse();
}const result = streamText({
model: openai('gpt-4'),
messages,
tools: {
search: {
description: 'Search the web',
parameters: z.object({ query: z.string() }),
execute: async ({ query }) => {
return await search(query);
}
}
}
});references/component-catalog.mdexample-reference.mdsetup-guide.mdtemplates/references/setup-guide.md