Morpha UI

Message

The layout shell of a chat message.

Overview

The structural half of a chat message: avatar + content column with optional header, footer and action rows, flipped with align="end" for the outgoing side. Pair it with Bubble for the speech surface and MessageScroller for the conversation viewport.

Typography follows the kit scale — the message body rides type-body (the same voice as Bubble), the header is a type-label-sm sender name and the footer a type-caption meta line. Both meta lines read in on-surface-variant so they recede behind the message itself.

Building an AI chat with useChat/streaming? The kit also ships Vercel AI Elements — see the AI section of these docs. Use these primitives when you want hand-rolled chat UI directly on the kit's tokens.

A
Ada
Hey! Did you ship the new kit?
09:41
Just now — 61 components and counting.
09:42 · Read
$ npx morpha-ui add message

Examples

Avatar

The avatar is pinned to the bottom of the column, so it always hugs the last bubble of the turn. align="end" reverses the row for the outgoing side.

L
Incoming — avatar on the left.
ME
Outgoing — align="end" flips the row.

Group

Consecutive turns from the same sender: one Message shell wrapping a BubbleGroup, with a single avatar and timestamp for the whole run.

A
Ada
Pushed the token pass to main.
Typography is on the kit scale now.
Dark mode included 🌙
09:41
Pulling it now.
Looks great on the docs site.
09:43 · Read

MessageHeader names the sender; MessageFooter carries the time and delivery state.

A
Ada LovelaceDesign
Can you review the elevation tokens today?
09:41
On it — I'll leave notes in the thread.
09:42Read

Actions

MessageActions holds message-level controls — copy, retry, feedback. The row is visible by default, since a generated reply always carries its controls. Pass reveal="hover" for the quieter treatment, where it fades in lifting a soft blur once the message is hovered or focused (and stays permanently visible on devices that can't hover).

Each control is a MessageAction: a containerless icon button named by a plain tooltip on hover. MessageCopyAction is the ready-made copy control — it writes text to the clipboard and swaps its glyph to a check for two seconds to confirm.

Summarise the Cupido elevation scale.
Six levels, each a pair of shadows — a tight ambient layer plus a softer spread. Light mode tints them with the neutral gray; dark mode drops to pure black at the same opacities.
Morpha · 09:44

Attachment

Images and files sit inside MessageContent as siblings of the bubble: media in a bare ghost bubble, files in the kit's Attachment chip.

A
Ada
Gradient cover exported from Figma
Cover's exported — specs are in the PDF.
elevation-spec.pdf2.4 MB · PDF
09:41
Got it — downloading now.
09:42 · Read

Branching

MessageBranch navigates alternative versions of one turn (regenerated replies): MessageBranchContent shows only the active child, and the selector row — previous, "1 of 3", next — rides the same type-caption meta voice as the header/footer lines, wrapping around at the ends. MessageToolbar lays the selector and MessageActions out on one row.

The quickest fix is memoizing the table data with useMemo so the reference stays stable between renders.
0 of 0

Installation

Morpha UI components are distributed via the Morpha CLI: npx morpha-ui add message. In the meantime, since this is the base shadcn component, you can also add it directly:

npx shadcn@latest add message

API Reference

Prop

Type

MessageActions

Prop

Type

MessageAction

Prop

Type

MessageCopyAction

Prop

Type

MessageBranch

Prop

Type

Anatomy

<MessageGroup>
  <Message align="start">
    <MessageAvatar />
    <MessageContent>
      <MessageHeader />
      <MessageBranch>
        <MessageBranchContent>
          <Bubble>
            <BubbleContent />
          </Bubble>
        </MessageBranchContent>
        <MessageToolbar>
          <MessageBranchSelector>
            <MessageBranchPrevious />
            <MessageBranchPage />
            <MessageBranchNext />
          </MessageBranchSelector>
          <MessageActions />
        </MessageToolbar>
      </MessageBranch>
      <MessageFooter />
    </MessageContent>
  </Message>
</MessageGroup>

MessageGroup, MessageAvatar, MessageContent, MessageHeader, MessageFooter, MessageActions and MessageToolbar take no props of their own — they are plain divs and accept className plus any native attribute. Branching is optional: without alternatives, put the Bubble directly in MessageContent.

Accessibility

  • Keep sender and time visible (header/footer) — alignment and color alone don't convey who is speaking.
  • Icon-only controls in MessageActions need an aria-label; the row is keyboard reachable and reveals itself on focus.
  • The shell is plain content; interactive parts inside (links, reactions, attachments) carry their own semantics.

On this page