Message

Chat message bubbles, attachments, and conversation markers.

Quick Preview

Hi! Is the 3-bedroom in Lekki still available for a viewing this week?

Yes, it is. I have a slot at 3 PM on Thursday.

I'll send the address and a map link shortly.

Sent on your behalf by AI

Perfect — see you then.

Composition

Message is the bubble shell. It owns direction, size, the tail corner, and the meta row (timestamp + read receipt), and exposes size/direction to its parts through data-* attributes — so the content and attachment slots size and colour themselves with no props of their own.

MessageGroup
├── Marker (optional — date divider, system notice, unread line)
└── Message (direction, size, timestamp, status, footer)
    ├── MessageContent            (prose)
    ├── MessageMedia              (image / video)
    │   ├── MessageMediaImage | MessageMediaPlaceholder
    │   ├── MessageMediaPlay
    │   └── MessageMediaDuration
    ├── MessageFile               (document)
    │   ├── MessageFileIcon
    │   ├── MessageFileInfo › MessageFileName · MessageFileDetail
    │   └── MessageFileAction
    └── MessageVoice              (voice note)
        ├── MessageVoicePlay
        ├── MessageVoiceWaveform
        └── MessageVoiceDuration

Pick exactly one content slot per bubble — MessageContent, MessageMedia, MessageFile, or MessageVoice. The shell renders the meta row itself.

Usage

<MessageGroup>
  <Message direction="received" timestamp="14:30">
    <MessageContent render={<p />}>Is it still available?</MessageContent>
  </Message>

  <Message direction="sent" status="read" timestamp="14:32" footer="Sent by AI">
    <MessageContent render={<p />}>Yes — see you there.</MessageContent>
  </Message>
</MessageGroup>

Examples

Conversation thread

Set direction per side and pass a timestamp. Sent messages show the Figma read-receipt tick by default; set showReadReceipt={false} to hide it. Use status="delivered" to change its accessible label or status="failed" to render legible failure text instead of an icon. The optional footer sits below a sent bubble for quiet attribution.

Hi! Is the 3-bedroom in Lekki still available for a viewing this week?

Yes, it is. I have a slot at 3 PM on Thursday.

I'll send the address and a map link shortly.

Sent on your behalf by AI

Perfect — see you then.

Attachments

Swap MessageContent for MessageMedia, MessageFile, or MessageVoice. Each reads the bubble's size and direction from the shell, so a picture, a document, and a voice note line up on the same ladder without extra props.

0:42

Offer-Letter.pdf

248 KB · PDF

0:12

Markers

Use Marker as a sibling of messages — not a child — for date dividers (variant="pill"), system notices, and unread lines. Give it real semantics with render (e.g. render={<h3 />}) since the same component serves several meanings.

Today

Morning — has the agent confirmed the paperwork?

Adaeze joined the conversation

Just did — everything is signed and filed.

Props

Prop/APITypeDefaultDescription
direction on Message"sent" | "received""sent"Conversation side. Drives fill, alignment, and the tail corner.
size on Message"sm" | "md" | "lg" | "xl""md"Size ladder for padding, radius, gaps, and type.
timestamp on MessageDate | string-Value for the <time> element. Omit to drop the timestamp.
timestampDateTime on MessageDate | string-Machine-readable value for a display-string timestamp.
status on Message"read" | "delivered" | "failed""read"Delivery receipt state. Sent-only; ignored when received.
showTimestamp / showReadReceipt on MessagebooleantrueToggle the meta-row parts.
footer on MessageReactNode-Quiet attribution below a sent bubble.
variant on Marker"default" | "pill""default"Full-width notice vs centred date pill.
size on Marker"sm" | "md" | "lg" | "xl""md"Match the surrounding bubbles.
alt on MessageMediaImagestring-Required — a chat photo is content, never decorative.
render on MessageContent / MessageFileAction / MarkerReactElement-Polymorphic element (e.g. <p />, <a download />, <h3 />).
classNamestring-Local layout or spacing overrides.
native/root propsReact component props-Passed through to the underlying element.

Accessibility

  • Preserve the documented composition so the bubble's size/direction context reaches its content and attachment slots.
  • MessageMediaImage requires alt; treat chat images as content, not decoration.
  • The read receipt does not rely on colour alone — read and delivered expose an accessible label, and failed renders text.
  • Give Marker real semantics with render where they exist (a heading for a date, role="separator" for an unread line).
  • Provide accessible names for the media, file, and voice controls; the play/download controls are real buttons with sensible defaults.

On this page