---
title: LLM Chat
description: A complete chat component with streaming responses, file uploads, and model selection for building AI-powered applications
component: true
links:
  source: https://github.com/deltacomponents/delta-ui/blob/main/registry/delta-ui/components/chat.tsx
  docs: https://ui.shadcn.com/docs/components/chat
---

<ComponentPreview name="chat-demo" height="600px" />

## Installation

<Installation name="chat" dependencies={["lucide-react", "streamdown"]} />

## Usage

```tsx
import { Chat } from "@/components/chat"
```

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

## Examples

### Chat with Previous Messages

<ComponentPreview name="chat-previous-messages-demo" height="600px" />

### 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.

<ComponentPreview name="chat-simple-demo" height="600px" />

### Chat with Shimmer Effect

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

<ComponentPreview name="chat-shimmer-demo" height="600px" />

### Chat with Reasoning

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

<ComponentPreview name="chat-reasoning-demo" height="600px" />

## API Reference

### Chat

| Prop              | Type                                                    | Default                                                                                                | Description                         |
| ----------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | ----------------------------------- |
| `allowFileUpload` | `boolean`                                               | `false`                                                                                                | Enable file upload functionality    |
| `userAvatar`      | `string`                                                | -                                                                                                      | Custom user avatar URL              |
| `models`          | `Model[]`                                               | `[{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            |
| `children`        | `ReactNode`                                             | -                                                                                                      | Custom content in chat options area |
| `className`       | `string`                                                | -                                                                                                      | 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

| Prop         | Type      | Default | Description                    |
| ------------ | --------- | ------- | ------------------------------ |
| `isDisabled` | `boolean` | -       | Whether the button is disabled |
| `isLoading`  | `boolean` | -       | Loading state indicator        |
| `className`  | `string`  | -       | Custom CSS classes             |

### ChatModelSelector

| Prop            | Type                        | Default | Description                 |
| --------------- | --------------------------- | ------- | --------------------------- |
| `selectedModel` | `string`                    | -       | Currently selected model ID |
| `onModelChange` | `(modelId: string) => void` | -       | Model selection callback    |
| `models`        | `Model[]`                   | -       | Available models array      |
| `className`     | `string`                    | -       | Custom CSS classes          |

### ChatOptions

| Prop        | Type        | Default | Description                        |
| ----------- | ----------- | ------- | ---------------------------------- |
| `children`  | `ReactNode` | -       | Content to display in options area |
| `className` | `string`    | -       | Custom CSS classes                 |

## Styling with Data Attributes

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

| Data Attribute                 | Target Element          | Description                      |
| ------------------------------ | ----------------------- | -------------------------------- |
| `[data-chat="send-button"]`    | Send button             | Style the submit button          |
| `[data-chat="model-selector"]` | Model selector dropdown | Style the model selection button |
| `[data-chat="options"]`        | Options container       | Style the options area           |
| `[data-chat="prompt-input"]`   | Prompt input container  | Style the entire input area      |
| `[data-chat="textarea"]`       | Textarea element        | Style the text input field       |

### Example CSS

```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:

```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

```tsx
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

```tsx
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

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

### Custom Styling with CSS

```tsx
// 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>
```

```css
/* 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

```tsx
<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

```tsx
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>
```
