LLM Chat

PreviousNext

A complete chat component with streaming responses, file uploads, and model selection for building AI-powered applications

Installation

pnpm dlx shadcn@latest add https://deltacomponents.dev/r/chat.json

Usage

import { Chat } from "@/components/chat"
<Chat onMessage={handleMessage} allowFileUpload={true} />

Examples

Chat with Previous Messages

Non-Streaming Chat

For use cases where LLM streaming doesn't happen and you receive the whole message in one go. Shows a loader until the message is received and then displays the complete message.

Chat with Shimmer Effect

Demonstrates the use of the shimmer component for loading states while AI processes requests.

Chat with Reasoning

Shows how to integrate the reasoning component to display AI thinking processes before responses.

API Reference

Chat

PropTypeDefaultDescription
allowFileUploadbooleanfalseEnable file upload functionality
userAvatarstring-Custom user avatar URL
modelsModel[][{id: 'gpt-4', name: 'GPT-4', model: 'GPT-4o'}, {id: 'claude', name: 'Claude', model: 'Claude 3.5'}]Available AI models
onMessage(message: string, modelId: string) => Promise<string>-Message handler function
childrenReactNode-Custom content in chat options area
classNamestring-Additional CSS classes

Individual Components

The chat component is composed of several modular components that can be used independently:

  • ChatMessages - Message display container
  • ChatUserMessage - User message bubble
  • ChatAssistantMessage - AI response message bubble
  • ChatPromptInput - Input area with model selection
  • ChatResponse - Streamdown markdown renderer
  • ChatStreamingResponse - Streaming text effect
  • ChatReasoning - "Thinking..." shimmer animation
  • ChatSendButton - Standalone send button component
  • ChatModelSelector - Model selection dropdown
  • ChatOptions - Container for custom content before input

ChatSendButton

PropTypeDefaultDescription
isDisabledboolean-Whether the button is disabled
isLoadingboolean-Loading state indicator
classNamestring-Custom CSS classes

ChatModelSelector

PropTypeDefaultDescription
selectedModelstring-Currently selected model ID
onModelChange(modelId: string) => void-Model selection callback
modelsModel[]-Available models array
classNamestring-Custom CSS classes

ChatOptions

PropTypeDefaultDescription
childrenReactNode-Content to display in options area
classNamestring-Custom CSS classes

Styling with Data Attributes

The chat component uses data attributes for easy CSS targeting without prop drilling:

Data AttributeTarget ElementDescription
[data-chat="send-button"]Send buttonStyle the submit button
[data-chat="model-selector"]Model selector dropdownStyle the model selection button
[data-chat="options"]Options containerStyle the options area
[data-chat="prompt-input"]Prompt input containerStyle the entire input area
[data-chat="textarea"]Textarea elementStyle the text input field

Example CSS

/* Custom send button styling */
[data-chat="send-button"] {
  background: linear-gradient(45deg, #ff6b6b, #ee5a52);
  border-radius: 50%;
}
 
/* Custom textarea styling */
[data-chat="textarea"] {
  background-color: #f8f9fa;
  border: 2px solid #e9ecef;
  font-family: "Inter", sans-serif;
}
 
/* Custom model selector styling */
[data-chat="model-selector"] {
  background-color: #495057;
  color: white;
  border-radius: 8px;
}
 
/* Custom options area */
[data-chat="options"] {
  padding: 16px;
  background-color: #f1f3f4;
  border-radius: 12px;
}

Features

  • Streaming Responses: Real-time text streaming with typewriter effect
  • File Upload: Drag & drop or click to upload files with preview
  • Model Selection: Dropdown to choose between different AI models
  • Rich Markdown: Full support for code blocks, tables, math, and more
  • Responsive Design: Works on desktop and mobile devices
  • Customizable: Modular components for flexible integration
  • TypeScript: Full type safety and IntelliSense support

Enhanced Scrollbar UI/UX

For a better scrollbar experience in your chat interface, add the thin-scrollbar utility class to your global CSS:

@utility thin-scrollbar {
  scrollbar-width: thin;
  scrollbar-color: rgb(163 163 163) transparent;
 
  &::-webkit-scrollbar {
    width: 2px;
    height: 2px;
  }
 
  &::-webkit-scrollbar-track {
    background: transparent;
  }
 
  &::-webkit-scrollbar-thumb {
    background-color: rgb(163 163 163);
    border-radius: 2px;
  }
 
  &::-webkit-scrollbar-thumb:hover {
    background-color: rgb(115 115 115);
  }
 
  @variant dark {
    scrollbar-color: rgb(82 82 82) transparent;
 
    &::-webkit-scrollbar-thumb {
      background-color: rgb(82 82 82);
    }
 
    &::-webkit-scrollbar-thumb:hover {
      background-color: rgb(115 115 115);
    }
  }
}

This utility provides:

  • Ultra-thin 2px scrollbars for a minimal, modern look
  • Neutral gray colors that work well with any theme
  • Dark mode support with appropriate contrast
  • Smooth hover interactions
  • Cross-browser compatibility

The ChatContainer component automatically applies this styling when the utility is available.

Examples

Custom Message Handler

const handleMessage = async (message: string, modelId: string) => {
  const response = await fetch("/api/chat", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ message, modelId }),
  })
 
  return response.text()
}
 
;<Chat onMessage={handleMessage} />

With Custom Models

const customModels = [
  { id: 'gpt-4', name: 'GPT-4', model: 'GPT-4o' },
  { id: 'claude', name: 'Claude', model: 'Claude 3.5 Sonnet' },
  { id: 'gemini', name: 'Gemini', model: 'Gemini Pro' }
]
 
<Chat models={customModels} />

With File Upload

<Chat allowFileUpload={true} onMessage={handleMessage} />

Custom Styling with CSS

// Add custom styles in your CSS file
<Chat className="my-custom-chat">
  <div className="flex items-center gap-2">
    <span>Custom controls here</span>
  </div>
</Chat>
/* Custom styling using data attributes */
.my-custom-chat [data-chat="send-button"] {
  background-color: #ef4444;
  transition: background-color 0.2s;
}
 
.my-custom-chat [data-chat="send-button"]:hover {
  background-color: #dc2626;
}
 
.my-custom-chat [data-chat="textarea"] {
  background-color: #f3f4f6;
  border-color: #d1d5db;
}
 
.my-custom-chat [data-chat="model-selector"] {
  color: #2563eb;
  border-color: #93c5fd;
}

Using ChatOptions

<Chat>
  <div className="bg-muted flex items-center justify-between rounded-md p-2">
    <span className="text-muted-foreground text-sm">AI Assistant</span>
    <button className="text-primary text-xs">Clear Chat</button>
  </div>
</Chat>

Individual Components

import {
  ChatAssistantMessage,
  ChatMessages,
  ChatModelSelector,
  ChatOptions,
  ChatPromptInput,
  ChatSendButton,
  ChatUserMessage,
} from "@/components/chat"
 
// Use components independently
 
;<div className="flex h-full flex-col">
  <ChatMessages messages={messages} isLoading={loading} />
  <ChatPromptInput
    input={input}
    onInputChange={setInput}
    onSubmit={handleSubmit}
    // ... other props
  />
</div>
 
// Or use individual components for custom layouts
;<div className="flex items-center gap-2">
  <ChatModelSelector
    selectedModel={model}
    onModelChange={setModel}
    models={models}
    className="rounded-md border"
  />
  <ChatSendButton
    isDisabled={!input.trim()}
    isLoading={loading}
    className="bg-green-500"
  />
</div>