showcase/shell-docs/src/content/reference/components/CopilotChatUserMessage.mdx
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 { CopilotChatUserMessage } from "@copilotkit/react-core/v2";
import "@copilotkit/react-core/v2/styles.css";
<PropertyReference name="onEditMessage" type="(props: { message: UserMessage }) => void"
Callback invoked when the user clicks the edit button. When not provided, the edit button is hidden from the toolbar. </PropertyReference>
<PropertyReference name="onSwitchToBranch" type="(props: { message: UserMessage; branchIndex: number; numberOfBranches: number }) => void"
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.
</PropertyReference>
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.
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" />
As a className:
<CopilotChatUserMessage
message={msg}
toolbar="opacity-0 group-hover:opacity-100 transition-opacity"
/>
<PropertyReference name="copyButton" type="SlotProp<typeof CopilotChatUserMessage.CopyButton>"
Slot for the copy-to-clipboard button. Defaults to
CopilotChatUserMessage.CopyButton. The tooltip label is sourced from
CopilotChatLabels.userMessageToolbarCopyMessageLabel.
</PropertyReference>
<PropertyReference name="editButton" type="SlotProp<typeof CopilotChatUserMessage.EditButton>"
Slot for the edit button. Defaults to CopilotChatUserMessage.EditButton.
Only rendered when onEditMessage is provided. The tooltip label is sourced
from CopilotChatLabels.userMessageToolbarEditMessageLabel.
</PropertyReference>
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>
)}
/>
function UserBubble({ message }) {
return <CopilotChatUserMessage message={message} />;
}
function EditableUserMessage({ message, onEdit }) {
return (
<CopilotChatUserMessage
message={message}
onEditMessage={({ message }) => onEdit(message)}
/>
);
}
function BranchedUserMessage({
message,
branchIndex,
totalBranches,
onSwitch,
}) {
return (
<CopilotChatUserMessage
message={message}
branchIndex={branchIndex}
numberOfBranches={totalBranches}
onSwitchToBranch={({ branchIndex }) => onSwitch(branchIndex)}
/>
);
}
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>
}
/>
);
}
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);
}}
/>
);
}
white-space: pre-wrap, so line breaks and spacing in the original message are preserved.numberOfBranches > 1 and onSwitchToBranch is provided. This prevents showing navigation for single-branch conversations.onEditMessage is provided.CopilotChatConfigurationProvider. See useCopilotChatConfiguration for available label keys.CopilotChatMessageView -- Parent component that uses this as the default user message slotCopilotChatAssistantMessage -- Companion component for assistant messagesuseCopilotChatConfiguration -- Provider for localized toolbar labels