Message

Inert message layout with avatar, header, content, footer, hover actions and bubbles, aligned to either side of a conversation.

1<Flex direction="column" gap={5} style={{ width: 440 }}>
2 <Message>
3 <Message.Avatar>
4 <Avatar size={3} radius="full" fallback="A" color="indigo" />
5 </Message.Avatar>
6 <Message.Header>Assistant</Message.Header>
7 <Message.Content>
8 <Message.Bubble variant="outline">
9 Here's the summary you asked for.
10 </Message.Bubble>
11 </Message.Content>
12 <Message.Footer>1:52 AM</Message.Footer>
13 </Message>
14 <Message align="end">
15 <Message.Content>

Anatomy

1import { Message } from '@raystack/apsara'
2
3<Message align="end">
4 <Message.Avatar>{/* Avatar */}</Message.Avatar>
5 <Message.Header>Ana</Message.Header>
6 <Message.Content>
7 <Message.Bubble>Hi there!</Message.Bubble>
8 </Message.Content>
9 <Message.Footer>1:52 AM</Message.Footer>
10 <Message.Actions>{/* copy / edit */}</Message.Actions>
11</Message>

Message is pure layout, with no context, no effects and no chat coupling. It works anywhere: inside a Chat scroller, a comment thread, or a standalone transcript. Scroll behavior (visibility tracking, turn anchoring) belongs to Chat. Wrap a message in Chat.Item to opt in.

Usage

A message is composed from parts. What follows covers those parts, how consecutive turns group together, and the bubble treatments.

Message anatomy

Avatar, header, footer and hover-revealed actions around the content column.

1<Flex direction="column" gap={5} style={{ width: 440 }}>
2 <Message>
3 <Message.Avatar>
4 <Avatar size={3} radius="full" fallback="A" color="indigo" />
5 </Message.Avatar>
6 <Message.Header>Assistant</Message.Header>
7 <Message.Content>
8 <Message.Bubble variant="outline">Hover me for actions.</Message.Bubble>
9 </Message.Content>
10 <Message.Footer>1:52 AM</Message.Footer>
11 <Message.Actions>
12 <IconButton size={1} aria-label="Copy message">
13
14 </IconButton>
15 </Message.Actions>

Grouped messages

Consecutive messages from one sender share a group; the avatar and timestamp appear once.

1<Flex direction="column" gap={5} style={{ width: 440 }}>
2 <Message.Group>
3 <Message>
4 <Message.Header>Ana</Message.Header>
5 <Message.Content>
6 <Message.Bubble variant="outline">Pushed the fix.</Message.Bubble>
7 </Message.Content>
8 </Message>
9 <Message>
10 <Message.Content>
11 <Message.Bubble variant="outline">CI is green again.</Message.Bubble>
12 </Message.Content>
13 </Message>
14 <Message>
15 <Message.Avatar>

Bubble variants

variant picks the surface treatment (solid, outline or ghost) and color the palette (neutral, accent or danger).

1<Flex direction="column" gap={3} align="start">
2 <Message.Bubble>The default: solid neutral.</Message.Bubble>
3 <Message.Bubble color="accent">High-emphasis accent bubble.</Message.Bubble>
4 <Message.Bubble color="danger">Something went wrong.</Message.Bubble>
5</Flex>

Ghost bubbles

variant="ghost" removes the surface, so there is no background, border or padding, and the bubble runs the full width of the message row instead of shrink-wrapping. It renders as plain body copy (Text at size="small"), which is the conventional treatment for assistant replies: the reader's own messages keep a bubble, the assistant's read as page content.

1<Flex direction="column" gap={5} style={{ width: 440 }}>
2 <Message align="end">
3 <Message.Content>
4 <Message.Bubble>Summarise the release notes for me.</Message.Bubble>
5 </Message.Content>
6 </Message>
7 <Message>
8 <Message.Avatar>
9 <Avatar size={3} radius="full" fallback="A" color="indigo" />
10 </Message.Avatar>
11 <Message.Header>Assistant</Message.Header>
12 <Message.Content>
13 <Message.Bubble variant="ghost">
14 Three things shipped: the timeline renderer, the AI element set, and a
15 rewrite of the token docs. The ghost bubble spans the whole row, so long

API Reference

A message, a group of them, and the bubble a message body sits in.

Message

One message. align drives which side everything sits on.

Prop

Type

Sub-parts are layout slots: Message.Avatar (bottom-aligned beside the message), Message.Header (sender line), Message.Content (the body column), Message.Footer (timestamp line) and Message.Actions (hover-revealed controls beside the bubble; always visible on touch devices).

Message.Group

A flex column that pulls consecutive messages from the same sender closer together. Render the avatar and footer once, typically on the group's last message.

Message.Bubble

The message surface.

Prop

Type

Slots

Every rendered part carries a stable data-slot attribute for styling and testing:

SlotElement
messageA single message row
message-groupWrapper around consecutive messages from one sender
message-avatarThe sender avatar
message-headerRow above the bubble, for sender name and timestamp
message-contentThe bubble holding the message body
message-actionsAction row revealed on the message
message-footerRow below the bubble

Accessibility

  • Message.Actions reveal on hover and on focus-within, and stay visible on touch devices, so keyboard and touch users are not locked out.
  • Message bodies are regular document content, so screen readers announce them in reading order with no extra semantics to configure.