# Chat thread

A React component in [Beamline](https://beamline.io/)'s [AI & agents](https://beamline.io/components/ai) category. Live demo: https://beamline.io/components/chat-thread

People talking to people: messages grouped by person and day, reactions, delivery and read receipts that glide to the newest message read, who is typing, and a composer with files; it scrolls on the same scroller as the agent conversation.

## Use it for

- Person-to-person or team chat inside a product: deal rooms, support handoffs, DMs.
- Threads where delivery, read state and reactions matter.

## Not for

- Talking to an agent ([conversation](https://beamline.io/components/conversation) + [message](https://beamline.io/components/message) + [response](https://beamline.io/components/response)).
- Comments attached to a document or record ([comment-thread](https://beamline.io/components/comment-thread)).
- A feed of system events ([timeline](https://beamline.io/components/timeline)).

## Anatomy

- root (surface)
- log (Conversation scroller, role log, named)
- day divider (Marker)
- group header: avatar, name, time
- bubble (mine: accent, right; others: surface, left)
- add-reaction button (hover/focus)
- reactions (toggle buttons with counts)
- attachments
- delivery status of my newest message (Sending, Sent, Delivered, Read)
- read-by avatars under the last message each person read
- failed line with reason and Retry
- typing line (status)
- jump-to-latest button
- composer: attach, field, send

## Variants

- **composer**: on (default), off (read-only, archived)

## States

- empty (emptyLabel)
- sending
- sent / delivered / read
- failed with Retry
- someone typing
- reading history (jump button)
- files attached to the draft
- controlled draft retained on rejection
- composer pending
- missing handler disabled

## Keyboard

- Enter sends, Shift+Enter starts a new line
- Tab reaches each message's reactions and add-reaction button; the picker is a popover (Escape closes, focus returns)
- The log scrolls with the keyboard; Jump to latest is a button
- Sending always takes the thread to the latest message

## Motion

Read-by avatars glide to the newest message read on the smooth spring (instant with reduced motion); the jump button arrives in --motion-in; typing dots pulse only while someone types (still under reduced motion); new messages follow with the conversation's smooth scroll.

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `participants / currentUserId` (required) | `ChatParticipant[] / string` | — | { id, name, avatar?, status? } |
| `messages / defaultMessages / onMessagesChange` | `ChatMessage[]` | — | { id, authorId, text, createdAt, attachments?, reactions?, status?, error?, edited? }, oldest first. |
| `onSend` | `(draft: { text, files }) => void \| Promise` | — | A promise shows Sending, then Sent, or the failure with Retry (uncontrolled). |
| `onRetry` | `(messageId) => void \| Promise` | — | Without it, locally sent records retry their original text and File objects through onSend. Preloaded messages have text only; supply onRetry to recover their files. |
| `onReact / reactions` | `(messageId, emoji) => void / string[]` | — |  |
| `typing / readBy` | `string[] / Record<participantId, messageId>` | — |  |
| `composer / allowAttachments / accept / placeholder` | `boolean / string` | — |  |
| `groupWindow / locale / label / emptyLabel` | `number / string / ReactNode` | — |  |
| `classNames` | `ChatThreadClassNames` | — |  |
| `style / ref` | `CSSProperties / native Ref` | — |  |
| `composerClassNames` | `ChatComposerClassNames` | — |  |
| `ChatComposer fieldRef` | `Ref<HTMLTextAreaElement>` | — |  |

## Built from

- conversation
- avatar
- attachment
- marker
- popover
- button

## Dependencies

`use-stick-to-bottom`, `lucide-react`, `motion`, `radix-ui`

## Import

```tsx
import { ChatThread, ChatComposer } from "@/components/chat-thread/chat-thread";
```

## Get it

Chat thread is part of Beamline: 190 React components and screens your coding agent (Claude Code, Codex, Cursor or any MCP client) installs into your app through Beamline's MCP server, as a ready-built package or as plain React source you can change. $49 one payment (regular $200), no subscription, a year of updates, one licence for your whole team. [Get Beamline](https://beamline.io/checkout?pack=complete) · [Connect your agent](https://beamline.io/connect)

## More in AI & agents

- [Approval card](https://beamline.io/components/approval-card): The agent stops and asks before it acts: what it wants to do, exactly what that changes, any choices it needs, and Approve or Reject; both run your…
- [Attachment](https://beamline.io/components/attachment): A file tile: preview or typed glyph with the type named, name, size, upload progress, error with retry, and a keyboard-reachable remove.
- [Citations](https://beamline.io/components/citations): Inline numbered citations that preview their source on hover or focus, plus a numbered source list; streamed answers flow in at an even pace with the…
- [Context cards](https://beamline.io/components/context-cards): The knowledge an agent retrieved before it answered: one card per chunk with what it is about, the text it read with the search words marked, how…
- [Conversation](https://beamline.io/components/conversation): The scrolling column of a conversation: follows new content while you are at the bottom, stops when you scroll up to read, and offers a way back; shared…
- [Flowchart](https://beamline.io/components/flowchart): A workflow as steps on a dotted canvas: a trigger, conditions that branch into paths side by side, actions and waits, read top to bottom; during a run…
- [Image generation](https://beamline.io/components/image-generation): The frame an AI image is generated into: a field of brand-hued pixels breathes with the progress while the model works, then the image arrives —…
- [Message](https://beamline.io/components/message): One turn in a conversation with an agent: the person's words in a quiet bubble, the agent's answer on the page with its orb mark, trace, tool calls and…
- [Plan](https://beamline.io/components/plan): An agent's plan: numbered steps with live status, progress, and Approve / Edit / Reject when it needs sign-off; approving shows progress, and a refusal…
- [Prompt bar](https://beamline.io/components/prompt-bar): The agent composer: a field that grows, @ to add a source, / for a command, a model picker, files and dictation, and one button that sends with progress…
- [Reasoning](https://beamline.io/components/reasoning): The agent's trace, fed by your stream: a shimmering label and the seconds so far while it works, then "Thought for N seconds"; steps that check off…
- [Recommendation card](https://beamline.io/components/recommendation-card): One suggestion from the agent that the person may take or leave: what it suggests, why, the expected effect and how sure it is (a meter and a word…
- [Response](https://beamline.io/components/response): An assistant's answer as streamed markdown in the system's reading type: bursty tokens flow in at an even pace, each new word fades in through a short…
- [Selection actions](https://beamline.io/components/selection-actions): Select a passage and hand it to the agent: a bar over the selection with quick actions, your own instruction and More; while the agent works it says so…
- [Task rows](https://beamline.io/components/task-rows): Background work an agent is doing, one row per task: status as a glyph and a word, what it produced, how long it has run or took, a progress bar while…
- [Tool call](https://beamline.io/components/tool-call): One tool call in an agent's run: status, what it did and a short result on one quiet row that opens to the exact input and output; stops for permission…
