CopilotChatUserMessage
Vue 3 component for displaying user-authored messages with copy, edit, and branch navigation.
This is the Vue 3 component. Import it from @copilotkit/vue/v2.
Overview
CopilotChatUserMessage renders a user-authored message aligned to the right of the chat. The default message renderer flattens the message content to text and displays it with white-space: pre-wrap so line breaks and spacing are preserved.
Below the message it renders a toolbar containing a copy-to-clipboard button, an optional edit button, and optional branch navigation controls. The toolbar becomes visible on hover. The edit button is only shown when an @edit-message listener is attached, and the branch navigation is only shown when numberOfBranches is greater than 1 and a @switch-to-branch listener is attached.
Example
<script setup lang="ts">
import { CopilotChatUserMessage } from "@copilotkit/vue/v2";
import "@copilotkit/vue/styles.css";
import type { UserMessage } from "@ag-ui/core";
const message: UserMessage = {
id: "1",
role: "user",
content: "What is the capital of France?",
};
</script>
<template>
<CopilotChatUserMessage :message="message" />
</template>Props
Prop
Type
Prop
Type
Prop
Type
Events
The action callbacks are emitted as Vue events. Attaching a listener for an event also enables the corresponding control: the edit button only renders when an @edit-message listener is present, and the branch navigation only renders when a @switch-to-branch listener is present (and numberOfBranches is greater than 1).
Prop
Type
Prop
Type
Slots
Each slot exposes scoped slot props (handlers and state) and falls back to the default rendering when not provided. Use a named template (<template #slot-name="...">) to override a slot.
Prop
Type
Prop
Type
Prop
Type
Prop
Type
Prop
Type
Prop
Type
Prop
Type
Usage
Basic user message
<script setup lang="ts">
import { CopilotChatUserMessage } from "@copilotkit/vue/v2";
import type { UserMessage } from "@ag-ui/core";
defineProps<{ message: UserMessage }>();
</script>
<template>
<CopilotChatUserMessage :message="message" />
</template>With edit support
<script setup lang="ts">
import { CopilotChatUserMessage } from "@copilotkit/vue/v2";
import type { UserMessage } from "@ag-ui/core";
defineProps<{ message: UserMessage }>();
function handleEdit(payload: { message: UserMessage }) {
console.log("Edit", payload.message.id);
}
</script>
<template>
<CopilotChatUserMessage :message="message" @edit-message="handleEdit" />
</template>With branch navigation
<script setup lang="ts">
import { ref } from "vue";
import { CopilotChatUserMessage } from "@copilotkit/vue/v2";
import type { UserMessage } from "@ag-ui/core";
defineProps<{ message: UserMessage; branches: UserMessage[] }>();
const currentBranch = ref(0);
function handleSwitch(payload: { branchIndex: number }) {
currentBranch.value = payload.branchIndex;
}
</script>
<template>
<CopilotChatUserMessage
:message="message"
:branch-index="currentBranch"
:number-of-branches="branches.length"
@switch-to-branch="handleSwitch"
/>
</template>Customizing appearance with slots
<script setup lang="ts">
import { CopilotChatUserMessage } from "@copilotkit/vue/v2";
import type { UserMessage } from "@ag-ui/core";
defineProps<{ message: UserMessage }>();
</script>
<template>
<CopilotChatUserMessage
:message="message"
@edit-message="({ message }) => console.log('Edit:', message.id)"
>
<template #message-renderer="{ content }">
<div class="rounded-2xl bg-blue-600 px-4 py-2 text-white">
{{ content }}
</div>
</template>
<template #toolbar-items>
<button @click="$emit('pin')">Pin</button>
</template>
</CopilotChatUserMessage>
</template>Full edit and branch workflow
<script setup lang="ts">
import { ref } from "vue";
import { CopilotChatUserMessage } from "@copilotkit/vue/v2";
import type { UserMessage } from "@ag-ui/core";
defineProps<{ message: UserMessage; branches: UserMessage[] }>();
const currentBranch = ref(0);
function openEditModal(message: UserMessage) {
// open your edit modal
}
</script>
<template>
<CopilotChatUserMessage
:message="message"
:branch-index="currentBranch"
:number-of-branches="branches.length"
@switch-to-branch="({ branchIndex }) => (currentBranch = branchIndex)"
@edit-message="({ message }) => openEditModal(message)"
/>
</template>Behavior
- Right-aligned layout: User messages are rendered with right-aligned positioning to visually distinguish them from assistant messages.
- Content flattening: When
message.contentis an array of parts, the default renderer joins thetextparts with newlines. String content is rendered as-is. - Whitespace preservation: The default message renderer uses
white-space: pre-wrap, so line breaks and spacing are preserved. The bubble gets extra vertical padding when the content is multiline. - Hover-revealed toolbar: The toolbar is invisible by default and becomes visible when the message is hovered.
- Transient copied state: After a successful copy, the copy button shows a check icon for 2 seconds before reverting.
- Conditional edit button: The edit button only appears when an
@edit-messagelistener is attached. - Conditional branch navigation: The branch navigation only appears when
numberOfBranchesis greater than 1 and a@switch-to-branchlistener is attached. - Localized labels: Toolbar button tooltips are sourced from the nearest configuration provider. See
useCopilotChatConfigurationfor available label keys.
Related
CopilotKitProvider- Supplies the CopilotKit context to descendant components.useCopilotChatConfiguration- Provider for localized toolbar labels.