CopilotChatUserMessage
Component for displaying user-authored messages with branch navigation
Overview
CopilotChatUserMessage shows user-authored messages aligned to the right with optional branch navigation. The default message renderer formats content with white-space: pre-wrap to preserve line breaks. Branch navigation controls only render when numberOfBranches is greater than 1 and an onSwitchToBranch handler is provided, enabling users to navigate between alternative conversation branches.
Import
Props
The user message object to render. Contains the message content, id, and
role.
Callback invoked when the user clicks the edit button. When not provided, the edit button is hidden from the toolbar.
Callback invoked when the user navigates to a different branch. Receives the
target branchIndex and total numberOfBranches. The branch navigation
controls are only rendered when this callback is provided and
numberOfBranches is greater than 1.
The zero-based index of the currently active branch. Used by the branch navigation controls to display the current position.
The total number of available branches for this message. Branch navigation is
only rendered when this value is greater than 1 and onSwitchToBranch is
provided.
Additional React elements appended to the toolbar alongside the default action buttons.
Slots
All slot props follow the CopilotKit slot system: each accepts a replacement React component, a className string that is merged into the default component's classes, or a partial props object that extends the default component.
Slot for the message content renderer. Defaults to CopilotChatUserMessage.MessageRenderer, which formats message text with white-space: pre-wrap to preserve whitespace and line breaks.
As a replacement component:
<CopilotChatUserMessage
message={msg}
messageRenderer={({ message }) => (
<div className="font-mono text-sm">{message.content}</div>
)}
/>
As a className:
<CopilotChatUserMessage message={msg} messageRenderer="text-lg font-medium" />
Slot for the action toolbar container. Defaults to CopilotChatUserMessage.Toolbar, which renders a horizontal row of action buttons below the message content.
As a className:
<CopilotChatUserMessage
message={msg}
toolbar="opacity-0 group-hover:opacity-100 transition-opacity"
/>
Slot for the copy-to-clipboard button. Defaults to
CopilotChatUserMessage.CopyButton. The tooltip label is sourced from
CopilotChatLabels.userMessageToolbarCopyMessageLabel.
Slot for the edit button. Defaults to CopilotChatUserMessage.EditButton.
Only rendered when onEditMessage is provided. The tooltip label is sourced
from CopilotChatLabels.userMessageToolbarEditMessageLabel.
Slot for the branch navigation controls. Defaults to CopilotChatUserMessage.BranchNavigation, which renders previous/next arrows and a branch counter (e.g., "2 / 3"). Only rendered when numberOfBranches is greater than 1 and onSwitchToBranch is provided.
As a replacement component:
<CopilotChatUserMessage
message={msg}
numberOfBranches={3}
branchIndex={1}
onSwitchToBranch={handleSwitch}
branchNavigation={({
branchIndex,
numberOfBranches,
onSwitchToBranch,
message,
}) => (
<div className="flex items-center gap-1 text-xs">
<button
onClick={() =>
onSwitchToBranch({
message,
branchIndex: branchIndex - 1,
numberOfBranches,
})
}
disabled={branchIndex === 0}
>
Prev
</button>
<span>
{branchIndex + 1} of {numberOfBranches}
</span>
<button
onClick={() =>
onSwitchToBranch({
message,
branchIndex: branchIndex + 1,
numberOfBranches,
})
}
disabled={branchIndex === numberOfBranches - 1}
>
Next
</button>
</div>
)}
/>
Usage
Basic User Message
function UserBubble({ message }) {
return <CopilotChatUserMessage message={message} />;
}
With Edit Support
function EditableUserMessage({ message, onEdit }) {
return (
<CopilotChatUserMessage
message={message}
onEditMessage={({ message }) => onEdit(message)}
/>
);
}
With Branch Navigation
function BranchedUserMessage({
message,
branchIndex,
totalBranches,
onSwitch,
}) {
return (
<CopilotChatUserMessage
message={message}
branchIndex={branchIndex}
numberOfBranches={totalBranches}
onSwitchToBranch={({ branchIndex }) => onSwitch(branchIndex)}
/>
);
}
Customizing Appearance with Slots
function StyledUserMessage({ message }) {
return (
<CopilotChatUserMessage
message={message}
messageRenderer="bg-blue-600 text-white rounded-2xl px-4 py-2"
toolbar="mt-1"
onEditMessage={({ message }) => console.log("Edit:", message.id)}
additionalToolbarItems={
<button onClick={() => console.log("Pin:", message.id)}>Pin</button>
}
/>
);
}
Full Edit and Branch Workflow
function FullFeaturedUserMessage({ message, branches }) {
const [currentBranch, setCurrentBranch] = useState(0);
return (
<CopilotChatUserMessage
message={message}
branchIndex={currentBranch}
numberOfBranches={branches.length}
onSwitchToBranch={({ branchIndex }) => setCurrentBranch(branchIndex)}
onEditMessage={({ message }) => {
// Open edit modal
openEditModal(message);
}}
/>
);
}
Behavior
- Right-Aligned Layout: User messages are rendered with right-aligned positioning to visually distinguish them from assistant messages.
- Whitespace Preservation: The default message renderer uses
white-space: pre-wrap, so line breaks and spacing in the original message are preserved. - Conditional Branch Navigation: The branch navigation controls are only rendered when both conditions are met:
numberOfBranches > 1andonSwitchToBranchis provided. This prevents showing navigation for single-branch conversations. - Conditional Edit Button: The edit button only appears in the toolbar when
onEditMessageis provided. - Localized Labels: Toolbar button tooltips are sourced from the nearest
CopilotChatConfigurationProvider. SeeuseCopilotChatConfigurationfor available label keys. - Slot System: Each slot prop accepts three forms -- a replacement component, a className string merged into the default, or a partial props object that extends the default component's props.
Related
CopilotChatMessageView-- Parent component that uses this as the default user message slotCopilotChatAssistantMessage-- Companion component for assistant messagesuseCopilotChatConfiguration-- Provider for localized toolbar labels