Chatbot
Response
A component that renders a Markdown response from a large language model.
The Response component renders a Markdown response from a large language model. It uses Streamdown under the hood to render the markdown.
"use client";import { Response } from "@/components/ai-elements/elements/response";import { useEffect, useState } from "react";const tokens = [ "### Hello", " World", "\n\n", "This", " is", " a", " **mark", "down", "**", " response", " from", " an", " AI", " model", ".", "\n\n", "---", "\n\n", "## Tables", "\n\n", "| Column 1", " | Column 2", " | Column 3", " |", "\n", "|----------|----------|----------|", "\n", "| Row 1, Col 1", " | Row 1, Col 2", " | Row 1, Col 3", " |", "\n", "| Row 2, Col 1", " | Row 2, Col 2", " | Row 2, Col 3", " |", "\n", "| Row 3, Col 1", " | Row 3, Col 2", " | Row 3, Col 3", " |", "\n\n", "## Blockquotes", "\n\n", "> This", " is", " a", " blockquote.", " It", " can", " contain", " multiple", " lines", " and", " **formatted**", " text.", "\n", ">", "\n", "> It", " can", " even", " have", " multiple", " paragraphs.", "\n\n", "## Inline", " Code", "\n\n", "Here", " is", " some", " text", " with", " `inline", " code`", " in", " the", " middle", " of", " a", " sentence.", " You", " can", " also", " use", " `const", " x", " =", " 42`", " for", " variable", " declarations.", "\n\n", "## Code", " Blocks", "\n\n", "```", "javascript", "\n", "const", " greeting", " = ", "'Hello, world!'", ";", "\n", "console", ".", "log", "(", "greeting", ")", ";", "\n", "```", "\n\n", "## Math", "\n\n", "It", " also", " supports", " math", " equations", ", ", "like", " this", " inline", " one", ": ", "$", "E", " = ", "mc", "^2", "$", ".", "\n\n", "And", " here", " is", " a", " display", " equation", " for", " the", " quadratic", " formula", ":", "\n\n", "$$", "\n", "x", " = ", "\\frac", "{", "-b", " \\pm", " \\sqrt", "{", "b^2", " -", " 4ac", "}", "}", "{", "2a", "}", "\n", "$$", "\n\n", "## Links", " and", " Lists", "\n\n", "Here's", " a", " [", "link", "](", "https://example.com", ")", " and", " some", " more", " text", " with", " an", " unordered", " list", ":", "\n\n", "-", " Item", " one", "\n", "-", " Item", " two", "\n", "-", " Item", " three", "\n\n", "## Ordered", " Lists", "\n\n", "1.", " First", " item", "\n", "2.", " Second", " item", "\n", "3.", " Third", " item",];const Example = () => { const [content, setContent] = useState(""); useEffect(() => { let currentContent = ""; let index = 0; const interval = setInterval(() => { if (index < tokens.length) { currentContent += tokens[index]; setContent(currentContent); index++; } else { clearInterval(interval); } }, 100); return () => clearInterval(interval); }, []); return <Response className="h-[500px]">{content}</Response>;};export default Example;Installation
npx ai-elements@latest add responsenpx shadcn@latest add @ai-elements/response"use client";import { cn } from "@repo/shadcn-ui/lib/utils";import { type ComponentProps, memo } from "react";import { Streamdown } from "streamdown";type ResponseProps = ComponentProps<typeof Streamdown>;export const Response = memo( ({ className, ...props }: ResponseProps) => ( <Streamdown className={cn( "size-full [&>*:first-child]:mt-0 [&>*:last-child]:mb-0", className )} {...props} /> ), (prevProps, nextProps) => prevProps.children === nextProps.children);Response.displayName = "Response";Important: After adding the component, you'll need to add the following to your globals.css file:
@source "../node_modules/streamdown/dist/index.js";This is required for the Response component to work properly. Without this import, the Streamdown styles will not be applied to your project. See Streamdown's documentation for more details.
Usage
import { Response } from '@/components/ai-elements/response';<Response>**Hi there.** I am an AI model designed to help you.</Response>Usage with AI SDK
Populate a markdown response with messages from useChat.
Add the following component to your frontend:
'use client';
import {
Conversation,
ConversationContent,
ConversationScrollButton,
} from '@/components/ai-elements/conversation';
import { Message, MessageContent } from '@/components/ai-elements/message';
import { useChat } from '@ai-sdk/react';
import { Response } from '@/components/ai-elements/response';
const ResponseDemo = () => {
const { messages } = useChat();
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': // we don't use any reasoning or tool calls in this example
return (
<Response key={`${message.id}-${i}`}>
{part.text}
</Response>
);
default:
return null;
}
})}
</MessageContent>
</Message>
))}
</ConversationContent>
<ConversationScrollButton />
</Conversation>
</div>
</div>
);
};
export default ResponseDemo;Features
- Renders markdown content with support for paragraphs, links, and code blocks
- Supports GFM features like tables, task lists, and strikethrough text via remark-gfm
- Supports rendering Math Equations via rehype-katex
- Smart streaming support - automatically completes incomplete formatting during real-time text streaming
- Code blocks are rendered with syntax highlighting for various programming languages
- Code blocks include a button to easily copy code to clipboard
- Adapts to different screen sizes while maintaining readability
- Seamlessly integrates with both light and dark themes
- Customizable appearance through className props and Tailwind CSS utilities
- Built with accessibility in mind for all users
Props
<Response />
Prop
Type