# Agent UI — Complete Documentation
> **@agent-ui/react** — 24 shadcn-style React components for building ChatGPT-class chat interfaces. WCAG AA, TypeScript, zero vendor lock-in.
**Version:** 0.1.0
**License:** MIT
**Repository:** https://github.com/agent-ui/agent-ui
**npm:** https://npmjs.com/@agent-ui/react
**Install:** `pnpm add @agent-ui/react`
---
## Table of Contents
1. [Installation](#installation)
2. [Core Chat Components](#core-chat-components)
- [MessageBubble](#messagebubble)
- [Composer](#composer)
- [MessageList](#messagelist)
- [ChatShell](#chatshell)
- [useChat](#usechat)
3. [Display Components](#display-components)
- [MarkdownContent](#markdowncontent)
- [CodeBlock](#codeblock)
- [Skeleton](#skeleton)
4. [Streaming Components](#streaming-components)
- [StreamingText](#streamingtext)
- [TypingIndicator](#typingindicator)
- [StopButton](#stopbutton)
- [CancelledBadge](#cancelledbadge)
5. [Agent / Tool Components](#agent--tool-components)
- [ToolCallCard](#toolcallcard)
- [ToolResult](#toolresult)
- [ThinkingBlock](#thinkingblock)
- [SourceCard](#sourcecard)
6. [Model / Provider Components](#model--provider-components)
- [ModelPicker](#modelpicker)
- [ProviderSelector](#providerselector)
7. [Input Components](#input-components)
- [Button](#button)
- [SuggestionChips](#suggestionchips)
8. [Chrome Components](#chrome-components)
- [ConversationSidebar](#conversationsidebar)
- [FeedbackButtons](#feedbackbuttons)
- [BranchPicker](#branchpicker)
9. [Protocol](#protocol)
- [dcmp](#dcmp)
10. [Demo Apps](#demo-apps)
11. [Architecture](#architecture)
12. [Accessibility](#accessibility)
---
## Installation
```bash
pnpm add @agent-ui/react
```
Each component is importable from its own subpath:
```tsx
import { MessageBubble } from "@agent-ui/react/message-bubble";
import { Composer } from "@agent-ui/react/composer";
import { useChat } from "@agent-ui/react/use-chat";
```
Or import everything from the barrel:
```tsx
import { Button, MessageBubble, ChatShell } from "@agent-ui/react";
```
---
## Core Chat Components
### MessageBubble
A chat message bubble with role-based styling. Supports user, assistant, and system roles.
**Import:** `@agent-ui/react/message-bubble`
```tsx
import { MessageBubble } from "@agent-ui/react/message-bubble";
```
#### Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `role` | `"user" \| "assistant" \| "system"` | required | Message role determines alignment and styling |
| `children` | `ReactNode` | required | Message content |
| `avatar?` | `string` | — | Avatar image URL |
| `name?` | `string` | — | Display name |
| `timestamp?` | `Date` | — | Message timestamp |
| `status?` | `"sending" \| "sent" \| "error"` | — | Delivery status indicator |
| `className?` | `string` | — | Additional CSS classes |
#### Example
```tsx
Hello! How can I help you today?
```
#### Accessibility
- Uses `` with `role="article"`
- `aria-label` set to "User message" / "Assistant message" / "System message"
- Status text rendered visually for delivery state
---
### Composer
A compound component for chat input with multiple slots. Uses React Context for state sharing between sub-components.
**Import:** `@agent-ui/react/composer`
```tsx
import { Composer } from "@agent-ui/react/composer";
```
#### Composer Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `onSend?` | `(text: string, attachments: File[]) => void` | — | Send handler |
| `disabled?` | `boolean` | — | Disables input and send |
| `className?` | `string` | — | Additional CSS classes |
| `children` | `ReactNode` | required | Slot components |
#### Slots
| Slot | Description |
|------|-------------|
| `Composer.Input` | Auto-resizing `textarea` with `@` mention detection, Enter to send, Shift+Enter for newline |
| `Composer.SendButton` | Send button, disabled when text is empty |
| `Composer.ProviderModelSlot` | Container for provider/model selector |
| `Composer.SkillSlot` | Container for skill selector |
| `Composer.AttachmentSlot` | Container for attachment preview |
| `Composer.SearchToggle` | Toggle button for web search (`aria-pressed`) |
| `Composer.ThinkingToggle` | Cycling toggle: off → low → medium → high → off |
| `Composer.MentionMenu` | Conditional `@` mention suggestions `listbox` |
#### Composer.Input Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `placeholder?` | `string` | `"Type a message..."` | Input placeholder |
| `className?` | `string` | — | Additional CSS classes |
#### Example
```tsx
console.log(text)}>
```
#### SimpleComposer
A pre-composed variant with just Input + SendButton:
```tsx
console.log(text)} />
```
#### Accessibility
- Textarea has `role="textbox"` and `aria-label="Message composer"`
- Send button has `aria-label="Send message"`
- Toggle buttons use `aria-pressed` for state
- MentionMenu uses `role="listbox"` and `aria-label="Mention suggestions"`
---
### MessageList
ARIA live region container for chat messages with auto-scroll and empty state.
**Import:** `@agent-ui/react/message-list`
```tsx
import { MessageList } from "@agent-ui/react/message-list";
```
#### Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `children?` | `ReactNode` | — | Message elements |
| `emptyMessage?` | `ReactNode` | `"Start a conversation"` | Empty state content |
| `isLoading?` | `boolean` | — | Shows loading state |
| `className?` | `string` | — | Additional CSS classes |
#### Example
```tsx
{messages.map(msg => (
{msg.content}
))}
```
#### Accessibility
- `role="log"` with `aria-live="polite"` for dynamic content announcements
- `aria-relevant="additions text"` for screen reader updates
- Focusable via `tabIndex={0}` for keyboard scrolling
---
### ChatShell
A pre-composed chat interface combining MessageList, MessageBubble, Composer, TypingIndicator, StopButton, and CancelledBadge.
**Import:** `@agent-ui/react/chat-shell`
```tsx
import { ChatShell } from "@agent-ui/react/chat-shell";
```
#### Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `messages` | `ChatMessage[]` | required | Array of chat messages |
| `isStreaming?` | `boolean` | — | Shows typing indicator + stop button |
| `error?` | `string \| null` | — | Shows error badge |
| `onSend?` | `(text: string) => void` | — | Send handler |
| `onStop?` | `() => void` | — | Stop generation handler |
| `placeholder?` | `string` | — | Composer placeholder |
| `className?` | `string` | — | Additional CSS classes |
#### Example
```tsx
function App() {
const { messages, isStreaming, error, send, stop } = useChat({
onSend: async (text) => { /* API call */ return response; },
});
return (
);
}
```
---
### useChat
React hook for chat state management.
**Import:** `@agent-ui/react/use-chat`
```tsx
import { useChat } from "@agent-ui/react/use-chat";
```
#### Types
```tsx
interface ChatMessage {
id: string;
role: "user" | "assistant" | "system";
content: string;
timestamp: Date;
status?: "sending" | "sent" | "error";
name?: string;
}
interface UseChatOptions {
initialMessages?: ChatMessage[];
onSend?: (message: string) => Promise;
}
```
#### Returns
| Property | Type | Description |
|----------|------|-------------|
| `messages` | `ChatMessage[]` | Current messages |
| `isStreaming` | `boolean` | True during response generation |
| `error` | `string \| null` | Error message if send failed |
| `send` | `(text: string) => Promise` | Send a message, await response |
| `stop` | `() => void` | Stop current generation |
| `clear` | `() => void` | Clear all messages |
#### Example
```tsx
const { messages, isStreaming, send, stop, clear } = useChat({
initialMessages: [{ id: "1", role: "assistant", content: "Hi!", timestamp: new Date() }],
onSend: async (text) => {
const res = await fetch("/api/chat", { method: "POST", body: JSON.stringify({ text }) });
return res.text();
},
});
```
---
## Display Components
### MarkdownContent
Renders GFM markdown with XSS protection. Supports headings, bold, inline code, fenced code blocks, links (with target="_blank"), ordered/unordered lists, and blockquotes.
**Import:** `@agent-ui/react/markdown-content`
```tsx
import { MarkdownContent } from "@agent-ui/react/markdown-content";
```
#### Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `content` | `string` | required | Markdown string |
| `className?` | `string` | — | Additional CSS classes |
#### Example
```tsx
```
#### Security
- Strips `