Navigation
Message
One chat message with its author, time, content, and streaming status.
When to use it: Use it for each entry inside Messages, especially when a reply streams in. A plain article is enough for static transcripts.
Example
import { Message, MessageAuthor, MessageContent, MessageTime, Messages } from "@comp0/react";
export function Example() {
return (
<Messages
aria-label="Conversation with the assistant"
className="flex w-full max-w-sm flex-col gap-3"
>
<Message
from="user"
className="self-end rounded-lg bg-teal-700 px-3 py-2 text-base text-white sm:text-sm"
>
<div className="flex items-baseline justify-between gap-3 text-sm opacity-80">
<MessageAuthor className="font-medium">You</MessageAuthor>
<MessageTime dateTime="2026-10-09T10:00:00Z">10:00</MessageTime>
</div>
<MessageContent>Summarize the accessibility audit.</MessageContent>
</Message>
<Message
from="assistant"
className="self-start rounded-lg bg-zinc-100 px-3 py-2 text-base text-zinc-900 sm:text-sm dark:bg-zinc-800 dark:text-zinc-100"
>
<div className="flex items-baseline justify-between gap-3 text-sm opacity-80">
<MessageAuthor className="font-medium">Assistant</MessageAuthor>
<MessageTime dateTime="2026-10-09T10:00:05Z">10:00</MessageTime>
</div>
<MessageContent>All 14 checks passed.</MessageContent>
</Message>
</Messages>
);
}Anatomy
Dashed frames are invisible state providers; shaded shapes own real DOM. Numbered pins match the list below.
A wireframe sketch of the assembled component. Each numbered marker matches a part in the list that follows.
Message
Article for one message; busy while its status is streaming. Owns a DOM element.
MessageAuthor
Visible name of the author. Owns a DOM element.
MessageTime
Time element for when it was sent. Owns a DOM element.
MessageContent
Body of the message. Owns a DOM element.
Step by step
- 1
Add the main part
Render one Message per entry inside Messages and set from to user, assistant, or system.
- 2
Add the supporting parts
Add MessageAuthor, MessageTime with a machine-readable dateTime, and MessageContent.
- 3
Make the behavior clear
Set status to streaming while content arrives, then complete or error. Set busy on Messages too so the log announces the message once.
Exampletsx <Messages aria-label="Conversation" busy={streaming}> <Message from="assistant" status={streaming ? "streaming" : "complete"}> <MessageAuthor>Assistant</MessageAuthor> <MessageContent>{reply}</MessageContent> </Message> </Messages>;
Keyboard
Forms and accessibility
Message creates no form values.
Accessibility checklist
- A streaming message is aria-busy so assistive technology waits for the finished text; also set busy on the enclosing Messages.
- Keep the author name visible; never rely on alignment or color to show who is speaking.
- Show an error as text, not only a color, and offer a retry control after it.
API reference
import { Message, MessageAuthor, MessageContent, MessageTime } from "@comp0/react";Message
DOM elementArticle for one message; busy while its status is streaming.
| Prop | Type | Description |
|---|---|---|
from | "user" | "assistant" | "system" | Who wrote it; exposed as data-from for styling. |
status | "streaming" | "complete" | "error" | Streaming sets aria-busy and makes nested comp0 parts hold warnings and focus moves. |
as | ElementType | Renders another element in place of the article. |
MessageAuthor
DOM elementVisible name of the author.
MessageTime
DOM elementTime element for when it was sent.
MessageContent
DOM elementBody of the message.
Style hooks
Attributes that appear while a state is true. Target them with Tailwind data variants such as data-open:bg-zinc-100, or with any CSS selector.
Message
| Style hook | Meaning |
|---|---|
[data-busy] | The message is streaming, or an ancestor is busy. |
[data-status] | streaming, complete, or error. |
[data-from] | user, assistant, or system. |