Logo

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 message
  • Shift + Enter - New line
  • Escape - 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