Message UI components
The default MessageUI is built from parts, and stream-chat-react exports them for a message UI of your own. Each part reads the message from MessageContext, so most need no props inside a message. Each is an override key of the same name, except MessageText: the default MessageUI renders the SDK's own. A message shows where each part sits.
Best practices
- Compose these parts instead of rebuilding them. They handle states that are easy to miss, such as a failed send, a thread reply or a message without text.
- Replace one part through its override key, and keep the rest of the default
MessageUI. - To change the action menu, change the action set, not the component. Actions explains how.
Available UI components
| Component | Renders | Props |
|---|---|---|
MessageActions |
The quick actions next to the message and the actions menu. | Below |
MessageAlsoSentInChannelIndicator |
"Also sent in channel" on a thread reply, or "Replied to a thread" in the channel, with a View button that jumps there. | onView, to replace what View does |
MessageBlocked |
"Message was blocked by moderation policies", in place of a removed or shadowed message. | none |
MessageBouncePrompt |
The prompt for a bounced message, see MessageBounceContext. | children, to replace the title and description |
MessageDeletedBubble |
"Message deleted", in place of the bubble. | none |
MessageEditedIndicator |
"Edited", with the edit time in a tooltip. | Below |
MessageRepliesCountButton |
The reply count and the avatars of the thread's participants. Clicking it opens the thread. | reply_count, thread_participants, onClick, labelSingle, labelPlural |
MessageStatus |
Sending, sent, delivered and read, on the user's own messages. | Below |
MessageText |
The text, through renderText, or the translation. |
message, renderText, customWrapperClass, customInnerClass |
MessageTimestamp |
The time the message was sent. | message, customClass, calendar, calendarFormats, format |
MessageTranslationIndicator |
"Translated from …", with a button to show the original. | message |
PinIndicator |
"Pinned by …" above the message. | message, required to render anything |
QuotedMessage |
The message this one quotes. Clicking it jumps to the quoted message. | renderText |
ReminderNotification |
The reminder set on the message, or "Saved for later". | reminder, required to render anything |
StreamedMessageText |
The text of an AI-generated message, a few letters at a time. | message, renderText, renderingLetterCount, streamingLetterIntervalMs |
A message prop replaces the message from the context. With one, MessageTimestamp also renders outside a message, for example in an override of the gallery header's time; without one, it throws outside a MessageProvider. Timestamp, the component MessageTimestamp and MessageEditedIndicator render the time with, isn't exported; replace it with the Timestamp override key.
For ReactionSelector, MessageReactions and MessageReactionsDetail, see Reaction components. For Attachment, see Attachments.
MessageActions props
| Prop | Type | Default | Description |
|---|---|---|---|
disableBaseMessageActionSetFilter |
boolean |
false |
Shows messageActionSet as it is, without removing what the user can't do or what doesn't apply to the message. |
messageActionSet |
MessageActionSetItem[] |
defaultMessageActionSet |
The actions. Each item has a Component and a placement: 'quick', 'dropdown' or 'quick-dropdown-toggle'. Every item but the toggle has a type too. |
The default set, and how to add, remove or replace an action, are on Actions. useBaseMessageActionSetFilter(set) runs the same filter on a set of your own.
MessageEditedIndicator props
MessageEditedIndicator renders only for a message with message_text_updated_at. The default MessageUI also leaves it out for AI-generated messages.
| Prop | Type | Default | Description |
|---|---|---|---|
calendar |
boolean | null |
from timestamp.MessageTimestamp |
Writes the edit time relative to today, such as "Yesterday at 14:32". |
calendarFormats |
Record<string, string> | string |
from timestamp.MessageTimestamp |
The calendar's formats, used with calendar. |
customClass |
string |
'str-chat__message-edited-indicator' |
Replaces the class of the outer span. |
format |
string |
from timestamp.MessageTimestamp |
A Day.js format for the edit time, such as HH:mm. |
message |
LocalMessage |
the context's message | The message whose edit time to show. |
The edit time in the tooltip goes through formatDate from the context first, when the list has one. Date and time formatting covers the keys and formats.
MessageStatus props
MessageStatus renders on the user's own messages only, and not on failed or error messages. In a thread it shows only "sending". "Sent" shows on the user's latest message, or on every own message with returnAllReadData.
| Prop | Type | Default | Description |
|---|---|---|---|
MessageDeliveredStatus |
ComponentType |
a double check | Rendered when the message reached another member's device and nobody else has read it. |
MessageReadStatus |
ComponentType |
a double check, with a count when several read it | Rendered when another member read the message. The default tooltip lists the readers. |
MessageSendingStatus |
ComponentType |
a clock | Rendered while the message is sending. |
MessageSentStatus |
ComponentType |
a check | Rendered when the server has the message and no one else has received it yet. |
messageType |
string |
'simple' |
Used in the class names, as in str-chat__message-simple-status. |
tooltipUserNameMapper |
(user: UserResponse) => string |
user.name || user.id |
Turns each reader into the name the read tooltip shows. |
This replacement shows only first names in the read tooltip:
import type {
MessageStatusProps,
TooltipUsernameMapper,
} from "stream-chat-react";
import { MessageStatus, WithComponents } from "stream-chat-react";
const firstName: TooltipUsernameMapper = (user) =>
user.name?.split(" ")[0] ?? user.id;
const MessageStatusWithFirstNames = (props: MessageStatusProps) => (
<MessageStatus {...props} tooltipUserNameMapper={firstName} />
);
const overrides = { MessageStatus: MessageStatusWithFirstNames };
export const App = () => (
<WithComponents overrides={overrides}>
{/* the rest of the app */}
</WithComponents>
);Read state, unread and receipts explains where the read and delivery state comes from.
Hooks
useMessageContext()reads the message the parts render.useMessageAlsoSentInChannelNavigation()gives the jump that the View button ofMessageAlsoSentInChannelIndicatormakes, for a button of your own.useMessageReminder(messageId)returns the reminderReminderNotificationshows.