Core Components
Detailed guide to the main chat interface components
The core components form the foundation of any chat interface built with LlamaIndex Chat UI. These components work together to provide a complete chat experience.
ChatSection
The ChatSection
is the root component that provides context and layout for all other chat components.
Basic Usage
import { ChatSection } from '@llamaindex/chat-ui'
import { useChat } from '@ai-sdk/react'
function MyChat() {
const handler = useChat({
transport: new DefaultChatTransport({
api: '/api/chat',
}),
})
return <ChatSection handler={handler} />
}
Props
interface ChatSectionProps {
handler: ChatHandler
className?: string
children?: React.ReactNode
}
- handler: Chat handler from
useChat
or custom implementation - className: Custom CSS classes for styling
- children: Custom layout (defaults to
ChatMessages
+ChatInput
) - autoOpenCanvas: Automatically opens the
ChatCanvas
when artifacts are present
Default Layout
When no children are provided, ChatSection
renders:
<>
<ChatMessages />
<ChatInput />
</>
Custom Layout
<ChatSection handler={handler} className="flex-row gap-4">
<div className="flex-1">
<ChatMessages />
<ChatInput />
</div>
<ChatCanvas className="w-1/3" />
</ChatSection>
ChatMessages
The ChatMessages
component displays the conversation history with automatic scrolling and loading states.
Basic Usage
import { ChatMessages } from '@llamaindex/chat-ui'
function MessageHistory() {
return (
<ChatMessages>
<ChatMessages.List>
{/* Custom message rendering */}
</ChatMessages.List>
</ChatMessages>
)
}
Sub-components
ChatMessages.List
Contains the actual message list with scroll management:
<ChatMessages.List className="px-4 py-6">
{messages.map((message, index) => (
<ChatMessage key={index} message={message} />
))}
</ChatMessages.List>
ChatMessages.Loading
Shows loading indicator when chat is processing:
<ChatMessages.Loading>
<div className="animate-pulse">Thinking...</div>
</ChatMessages.Loading>
ChatMessages.Empty
Displays when no messages exist:
<ChatMessages.Empty
heading="Welcome to Chat"
subheading="Start a conversation by typing below"
/>
ChatMessages.Actions
Action buttons for the message list:
<ChatMessages.Actions>
<button onClick={regenerate}>Regenerate</button>
<button onClick={stop}>Stop</button>
</ChatMessages.Actions>
Features
- Auto-scroll - Automatically scrolls to new messages
- Loading states - Shows when chat is processing
- Empty state - Customizable welcome message
- Performance - Optimized for large message histories
ChatMessage
Individual message component which renders, the avatar, the content and actions of a message.
Basic Usage
import { ChatMessage } from '@llamaindex/chat-ui'
function CustomMessage({ message, isLast }) {
return (
<ChatMessage message={message} isLast={isLast}>
<ChatMessage.Avatar>
<UserAvatar role={message.role} />
</ChatMessage.Avatar>
<ChatMessage.Content>
<ChatMessage.Part.Markdown />
</ChatMessage.Content>
<ChatMessage.Actions />
</ChatMessage>
)
}
Props
interface ChatMessageProps {
message: Message
isLast?: boolean
className?: string
children?: React.ReactNode
}
Message Structure
The Message data structure stores the content of a message in so called parts:
interface Message {
id: string
role: 'user' | 'assistant' | 'system'
parts: MessagePart[]
}
Sub-components
ChatMessage.Avatar
User/assistant avatar display:
<ChatMessage.Avatar>
<div className="flex h-8 w-8 items-center justify-center rounded-full bg-blue-500">
{message.role === 'user' ? 'U' : 'AI'}
</div>
</ChatMessage.Avatar>
ChatMessage.Content
This is the main content area which configures a couple of renders for specific message parts:
<ChatMessage.Content>
<ChatMessage.Part.Markdown />
<ChatMessage.Part.Artifact />
<ChatMessage.Part.Sources />
<ChatMessage.Part.Event />
<ChatMessage.Part.File />
<ChatMessage.Part.Suggestion />
</ChatMessage.Content>
ChatMessage.Actions
Message-level actions (copy, regenerate, etc.):
<ChatMessage.Actions>
<button onClick={copyMessage}>Copy</button>
<button onClick={regenerate}>Regenerate</button>
</ChatMessage.Actions>
Message Parts
There are different renderers available for each part in the message:
- TextPart - Rich text with Markdown and LaTeX support
- ArtifactPart - Interactive code/document editing
- SourcesPart - Citation and source links
- EventPart - Process events and status updates
- FilePart - File attachments and uploads
- SuggestedQuestionsPart - Follow-up question suggestions
ChatInput
Input component with file upload support and keyboard shortcuts.
Basic Usage
import { ChatInput } from '@llamaindex/chat-ui'
function MessageInput() {
return (
<ChatInput>
<ChatInput.Form>
<ChatInput.Field placeholder="Type your message..." />
<ChatInput.Upload />
<ChatInput.Submit />
</ChatInput.Form>
</ChatInput>
)
}
Sub-components
ChatInput.Form
Form wrapper with submit handling:
<ChatInput.Form onSubmit={handleSubmit}>
{/* Input components */}
</ChatInput.Form>
ChatInput.Field
Auto-resizing textarea with keyboard shortcuts:
<ChatInput.Field
placeholder="Type your message..."
disabled={isLoading}
className="min-h-12 max-h-32"
/>
Keyboard Shortcuts:
Enter
- Submit messageShift + Enter
- New lineEscape
- Clear input
ChatInput.Upload
File upload trigger:
<ChatInput.Upload>
<button type="button">
<PaperclipIcon className="h-4 w-4" />
</button>
</ChatInput.Upload>
ChatInput.Submit
Submit button with loading state:
<ChatInput.Submit>
<button type="submit" disabled={isLoading}>
<SendIcon className="h-4 w-4" />
</button>
</ChatInput.Submit>
Features
- Auto-resize - Textarea grows with content
- File upload - Drag & drop or click to upload
- Keyboard shortcuts - Intuitive message sending
- Loading states - Disabled during processing
- Validation - Built-in input validation
ChatCanvas
Side panel component for displaying interactive artifacts like code and documents.
Basic Usage
import { ChatCanvas } from '@llamaindex/chat-ui'
function ChatWithCanvas() {
return (
<div className="flex h-full">
<div className="flex-1">
<ChatMessages />
<ChatInput />
</div>
<ChatCanvas className="w-1/2" />
</div>
)
}
Features
- Slide Animation - Smooth slide-in when artifacts appear
- Version Management - Track changes to artifacts
- Edit Support - Interactive editing for code and documents
- Responsive - Adapts to different screen sizes
Artifact Types
Code Artifacts
<ChatCanvas>
<ChatCanvas.CodeArtifact
filename="example.py"
language="python"
code="print('Hello, world!')"
/>
</ChatCanvas>
Document Artifacts
<ChatCanvas>
<ChatCanvas.DocumentArtifact
title="Meeting Notes"
content="# Meeting Summary\n\n..."
/>
</ChatCanvas>
Component Composition
Full Custom Layout
function AdvancedChat() {
const handler = useChat({
transport: new DefaultChatTransport({
api: '/api/chat',
}),
})
return (
<ChatSection handler={handler} className="flex h-full">
<div className="flex flex-1 flex-col">
<header className="border-b p-4">
<h1>My Chat App</h1>
</header>
<ChatMessages className="flex-1">
<ChatMessages.List className="p-4">
{/* Custom message rendering */}
</ChatMessages.List>
<ChatMessages.Loading>
<CustomLoader />
</ChatMessages.Loading>
</ChatMessages>
<div className="border-t p-4">
<ChatInput>
<ChatInput.Form className="flex gap-2">
<ChatInput.Field className="flex-1" />
<ChatInput.Upload />
<ChatInput.Submit />
</ChatInput.Form>
</ChatInput>
</div>
</div>
<ChatCanvas className="w-1/2 border-l" />
</ChatSection>
)
}
Context Access
All components have access to chat context through hooks:
import { useChatUI, useChatMessage } from '@llamaindex/chat-ui'
function CustomComponent() {
const { messages, status, sendMessage } = useChatUI()
const { message } = useChatMessage() // Only in message context
// Component logic
}
Message Parts System
Each message can have multiple parts. Parts are rendered in the order they are received. For more information on parts, see Message Parts.
Creating Custom Parts
import { usePart } from '@llamaindex/chat-ui'
function CustomPart() {
const { data } = usePart()
return (
<div className="custom-part">
{/* Custom part rendering */}
</div>
)
}
Backend Integration
Parts can be sent from the backend via SSE protocol:
// Backend example
const parts = [
{ type: 'weather', data: weatherInfo },
{ type: 'sources', data: sourceNodes }
]
// Send as SSE
response.write(`data: ${JSON.stringify({ parts })}\n\n`)
Next Steps
- Widgets - Learn about specialized content widgets
- Message Parts - Implement rich content support with parts
- Hooks - Understand the hook system
- Customization - Style and theme the components