Summarize the launch risks. Keep the owners visible.
Preview
Design guidance
Use Message for one authored item in a transcript. Keep identity, attachments, reply content, status feedback, and actions caller-owned. A user message is the current user's own message by default; set self={false} for another human. System-authored content starts at the reading edge. Use Marker for joins, time labels, and other transcript boundaries.
Installation
Install the Message owner and its shared Chat model dependency.
Install
Source files
Basic usage
Message renders a named article. MessageBody keeps the surface and rich content inside the message measure.
Structures
Use MessageContent for the vertical header, body, and footer region. Put MessageAvatar beside it as a sibling of MessageContent; this keeps the avatar in its own fixed lane as text wraps. Legacy flat children still render in supplied order.
Examples
Independent alignment
Choose placement independently from actor. The incoming human example remains a user message and uses self={false}.
Marta joined the review
Identity, header, and footer
Keep the avatar beside the content stack. Header and delivery status stay with the message content.
Same-sender grouping
MessageGroup assigns first, middle, and last positions to adjacent direct Message children with the same actor, sender identity and effective alignment. Use senderId to distinguish participants in a shared chat. Different senders, alignments and non-Message children break a group.
Caller-owned reactions
Compose canonical Buttons inside MessageReactions. The caller owns pressed state, labels, and counts; MessageReactions only places the controls.
Reaction placement
Choose each side and alignment independently. The four examples cover top/start, top/end, bottom/start, and bottom/end.
People and agent
Use actor to describe the author, self={false} for another human, and identity only when the conversation needs it. A single agent reply can stay plain and omit its identity row.
Footer actions and timestamp
Copy and edit belong to the message footer. Hover, keyboard focus, or one tap reveals an own user's actions and time.
Context actions
Right-click or press and hold the message to open the canonical ContextMenu. Editing uses the same caller callback as the footer.
Edit and resubmit
The Composer holds the edit draft. Cancel keeps the original message. A successful submit updates caller state. Native runtime examples are on the Chat page.
Delivery details
The tiny check sits inside an own multiplayer bubble. Its Popover shows supplied recipient timestamps.
Plain
Keep assistant content directly on the surrounding surface.
Muted
Use a quiet surface for a user message.
Solid
Use the primary surface for a concise user message.
Tinted
Use the accent surface for supporting assistant content.
Outline
Add a boundary to a message that needs distinction from plain content.
Critical
Use the critical appearance with an error status when the release is blocked.
File and copy action
Keep file rows in caller-owned rich content. Copy reports pending, success, and failure through the action and status feedback.
Long content
Long caller-owned content wraps within the Message measure and remains alongside its identity lane.
Image
Provide media and its useful alternative text in MessageBody.
Reply
Compose a quoted reply inside caller-owned body content.
Voice transcript
Keep the transcript readable as caller-owned content.
Streaming and stopped output
Status changes set aria-busy during streaming and leave focus management with the caller.
API reference
Message
| Prop | Type | Default | Description |
|---|---|---|---|
actorrequired | ChatActor | Required author role: user, assistant, or system. | |
senderId | string | Optional stable participant identity. Adjacent messages group only when actor, senderId and alignment match. | |
status | MessageStatus | complete | Reports queued, streaming, complete, stopped, or error status. |
align | start | end | center | actor-and-self-derived | Sets placement independently of actor. Defaults to start for assistant, system, and incoming humans; own user messages default to end. |
self | boolean | true | Identifies an own user message. Set false for another human; this does not change actor. |
groupPosition | single | first | middle | last | single | Sets transcript spacing; an explicit value overrides MessageGroup context. |
label | string | Provides the accessible name when native naming props are absent. | |
children | ReactNode | Renders caller-owned parts or legacy flat children in supplied order. | |
...articleProps | ComponentPropsWithoutRef<'article'> | Forwards native article attributes and aria naming props; the component forwards its ref to the article. |
Message parts
| Prop | Type | Default | Description |
|---|---|---|---|
MessageContent | div part | Groups optional header, body, and footer in a vertical region; accepts native div props and ref. | |
MessageAvatar | div part | Use as a direct sibling of MessageContent for the fixed identity lane; accepts native div props and ref. | |
MessageHeader / MessageFooter / MessageAttachments | div part | Optional caller-owned regions; accept native div props and ref. | |
MessageBody.appearance | plain | muted | solid | tinted | outline | critical | actor-derived | Chooses the body surface. Defaults to plain for assistant/system and muted for user. |
MessageBody.actor | ChatActor | Overrides inherited actor only for body appearance and data. | |
MessageBody.children | ReactNode | Caller-owned text, rich media, attachments, replies, or MessageReactions. |
Grouping and reactions
| Prop | Type | Default | Description |
|---|---|---|---|
MessageGroup.children | ReactNode | Groups adjacent direct Message children only when actor, senderId and effective alignment match; any other child breaks adjacency. | |
MessageReactions.side | top | bottom | bottom | Places caller-provided controls above or below the relative MessageBody. |
MessageReactions.align | start | end | end | Places reaction controls at the inline start or end edge. |
MessageReactions.children | ReactNode | Caller-owned controls such as Buttons with accessible names, aria-pressed state, and counts. |
Accessibility
Message renders a named article. Native aria-labelledby, then aria-label, then label take precedence over the actor fallback. Streaming sets aria-busy without creating a live region or moving focus. Give every reaction Button an accessible name that includes its meaning and current count, and expose its selected state with aria-pressed.
