ChatMessage
Composable chat message with stable inline editing, bubble or flat layout, grouped bursts, reactions, and replies.
Examples
Team conversation
People talking to people: layout="flat" keeps everyone on the start edge, continuation folds a burst under one author, and reactions and reply summaries hang off the body.
Composition
Editable message
ChatMessageEditable owns the plain-text draft and defaults to Copy/Edit actions. The host persists onSave; rejection keeps the draft for retry. Escape cancels, Ctrl/Cmd+Enter saves, and Enter inserts a newline. Optional children customize the read-mode ActionBar.
- <ChatMessage>
- <ChatMessageRow>
- <ChatMessageBody>
- <ChatMessageEditable>
- value={text} onSave={saveMessage}
- <ChatMessageEditable>
- <ChatMessageBody>
- <ChatMessageRow>
Message with actions
- <ChatMessage>
- <ChatMessageRow>
- <ChatMessageAvatar />
- <ChatMessageBody>
- <ChatMessageHeader />
- <ChatMessageContent>
- message content
- <ChatMessagePending />
- <ChatMessageActions>
- <ActionBar />
- <ChatMessageRow>
Team message
- <ChatMessage>
- from="participant" layout="flat"
- <ChatMessageRow>
- <ChatMessageAvatar>
- Avatar, or ChatMessageTime on a continuation
- <ChatMessageBody>
- <ChatMessageHeader>
- <ChatMessageAuthor />
- <ChatMessageTime />
- <ChatMessageContent>
- message content
- <ChatMessageFooter />
- <ChatMessageReactions>
- <ChatMessageReaction />
- <ChatMessageReplySummary />
- <ChatMessageReplies />
- <ChatMessageHeader>
- <ChatMessageActions>
- <ActionBar />
- <ChatMessageAvatar>
Typing indicator
- <ChatTypingIndicator>
- who is typing
Installation
Use this command to install the component.
Usage
Dependencies
src/registry/hooks/use-chat-message.tsHooksrc/registry/sources/control-ui/chat-message/social.tsxSupportsrc/registry/sources/control-ui/effects.cssSupportaction-barComponentLive statuslive-statusPrimitiveRaw code
Installed component source and support files
Knobs
Typed custom properties the recipe paints with. Set one on the root — style, a utility class, or a skin — and every slot inherits it.
--cui-chat-message-* · 21 knobsHow the cascade resolves--cui-chat-message-avatar-radius<length-percentage>9999px--cui-chat-message-avatar-background<color>var(--card)--cui-chat-message-avatar-border-color<color>var(--border)--cui-chat-message-avatar-border-width<length>var(--control-rim-width)--cui-chat-message-radius<length-percentage>0px--cui-chat-message-corner-radius<length-percentage>0px--cui-chat-message-background<color>transparent--cui-chat-message-background-image*none--cui-chat-message-foreground<color>var(--foreground)--cui-chat-message-border-color<color>transparent--cui-chat-message-border-width<length>0px--cui-chat-message-shadow*none--cui-chat-message-pending-dot-color<color>var(--muted-foreground)--cui-chat-message-pending-dot-size<length-percentage>calc(var(--spacing) * 1.5)--cui-chat-message-row-hover-background<color>oklch(from var(--muted) l c h / 0.6)--cui-chat-message-reaction-radius<length-percentage>9999px--cui-chat-message-reaction-background<color>oklch(from var(--muted) l c h / 0.7)--cui-chat-message-reaction-border-color<color>transparent--cui-chat-message-reaction-border-width<length>var(--control-rim-width)--cui-chat-message-reaction-pressed-background<color>oklch(from var(--primary) l c h / 0.14)--cui-chat-message-reaction-pressed-border-color<color>oklch(from var(--primary) l c h / 0.55)