ChatMessage 组件为 user 或 assistant 聊天消息渲染一个 <article> 元素。
ChatMessages 组件来显示聊天消息列表。使用 parts 属性以 AI SDK v5 格式显示消息内容。
<template>
<UChatMessage
:parts="[
{
type: 'text',
id: '1',
text: 'Hello! Tell me more about building AI chatbots with Nuxt UI.'
}
]"
role="user"
id="1"
/>
</template>
parts 属性是 AI SDK v5 的推荐格式。每个部分都有一个 type(例如,“text”)和相应的内容。ChatMessage 组件也支持已弃用的 content 属性以实现向后兼容。使用 side 属性在左侧或右侧显示消息。
<template>
<UChatMessage
side="right"
:parts="[
{
type: 'text',
id: '1',
text: 'Hello! Tell me more about building AI chatbots with Nuxt UI.'
}
]"
role="user"
id="1"
/>
</template>
使用 variant 属性更改消息样式。
<template>
<UChatMessage
variant="soft"
:parts="[
{
type: 'text',
id: '1',
text: 'Hello! Tell me more about building AI chatbots with Nuxt UI.'
}
]"
role="user"
id="1"
/>
</template>
使用 icon 属性在消息旁边显示一个 Icon 组件。
<template>
<UChatMessage
icon="i-lucide-user"
variant="soft"
side="right"
:parts="[
{
type: 'text',
id: '1',
text: 'Hello! Tell me more about building AI chatbots with Nuxt UI.'
}
]"
role="user"
id="1"
/>
</template>
使用 avatar 属性在消息旁边显示一个 Avatar 组件。
<template>
<UChatMessage
:avatar="{
src: 'https://github.com/benjamincanac.png'
}"
variant="soft"
side="right"
:parts="[
{
type: 'text',
id: '1',
text: 'Hello! Tell me more about building AI chatbots with Nuxt UI.'
}
]"
role="user"
id="1"
/>
</template>
您还可以使用 avatar.icon 属性将图标显示为头像。
<template>
<UChatMessage
:avatar="{
icon: 'i-lucide-bot'
}"
:parts="[
{
type: 'text',
id: '1',
text: 'Nuxt UI offers several features for building AI chatbots including the ChatMessage, ChatMessages, and ChatPrompt components. Best practices include using the Chat class from AI SDK v5, implementing proper message styling with variants, and utilizing the built-in actions for message interactions. The components are fully customizable with theming support and responsive design.'
}
]"
role="assistant"
id="1"
/>
</template>
使用 actions 属性在消息下方显示操作,当鼠标悬停在消息上时将显示这些操作。
<script setup lang="ts">
const actions = ref([
{
label: 'Copy to clipboard',
icon: 'i-lucide-copy'
}
])
</script>
<template>
<UChatMessage
:actions="actions"
:parts="[
{
type: 'text',
id: '1',
text: 'Nuxt UI offers several features for building AI chatbots including the ChatMessage, ChatMessages, and ChatPrompt components. Best practices include using the Chat class from AI SDK v5, implementing proper message styling with variants, and utilizing the built-in actions for message interactions. The components are fully customizable with theming support and responsive design.'
}
]"
role="user"
id="1"
/>
</template>
| 属性 | 默认值 | 类型 |
|---|---|---|
as |
|
此组件应渲染为的元素或组件。 |
id |
消息的唯一标识符。 | |
角色 |
消息的角色。 | |
部分 |
消息的部分。用于在 UI 中渲染消息。 应避免系统消息(而应在服务器上设置系统提示)。它们可以包含文本部分。 用户消息可以包含文本部分和文件部分。 助手消息可以包含文本、推理、工具调用和文件部分。
| |
图标 |
| |
avatar |
| |
variant |
|
|
side |
|
|
actions |
在消息下方显示操作列表。工具提示中将使用
| |
紧凑 |
|
以紧凑样式渲染消息。在 |
内容 |
| |
元数据 |
消息的元数据。 | |
ui |
|
| 插槽 | 类型 |
|---|---|
前置 |
|
内容 |
|
actions |
|
export default defineAppConfig({
ui: {
chatMessage: {
slots: {
root: 'group/message relative w-full',
container: 'relative flex items-start',
leading: 'inline-flex items-center justify-center min-h-6',
leadingIcon: 'shrink-0',
leadingAvatar: 'shrink-0',
leadingAvatarSize: '',
content: 'relative text-pretty min-w-0 *:first:mt-0 *:last:mb-0',
actions: [
'opacity-0 group-hover/message:opacity-100 absolute bottom-0 flex items-center',
'transition-opacity'
]
},
variants: {
variant: {
solid: {
content: 'bg-inverted text-inverted'
},
outline: {
content: 'bg-default ring ring-default'
},
soft: {
content: 'bg-elevated/50'
},
subtle: {
content: 'bg-elevated/50 ring ring-default'
},
naked: {
content: ''
}
},
side: {
left: {
container: 'rtl:justify-end'
},
right: {
container: 'ltr:justify-end ms-auto max-w-[75%]'
}
},
leading: {
true: ''
},
actions: {
true: ''
},
compact: {
true: {
root: 'scroll-mt-3',
container: 'gap-1.5 pb-3',
leadingIcon: 'size-5',
leadingAvatarSize: '2xs'
},
false: {
root: 'scroll-mt-4 sm:scroll-mt-6',
container: 'gap-3 pb-8',
leadingIcon: 'size-8',
leadingAvatarSize: 'md'
}
}
},
compoundVariants: [
{
compact: true,
actions: true,
class: {
container: 'pb-8'
}
},
{
leading: true,
compact: false,
side: 'left',
class: {
actions: 'left-11'
}
},
{
leading: true,
compact: true,
side: 'left',
class: {
actions: 'left-6.5'
}
},
{
variant: [
'solid',
'outline',
'soft',
'subtle'
],
compact: false,
class: {
content: 'px-4 py-3 rounded-lg min-h-12',
leading: 'mt-2'
}
},
{
variant: [
'solid',
'outline',
'soft',
'subtle'
],
compact: true,
class: {
content: 'px-2 py-1 rounded-lg min-h-8',
leading: 'mt-1'
}
},
{
variant: 'naked',
side: 'left',
class: {
content: 'w-full'
}
}
],
defaultVariants: {
variant: 'naked'
}
}
}
})
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nuxt/ui/vite'
export default defineConfig({
plugins: [
vue(),
ui({
ui: {
chatMessage: {
slots: {
root: 'group/message relative w-full',
container: 'relative flex items-start',
leading: 'inline-flex items-center justify-center min-h-6',
leadingIcon: 'shrink-0',
leadingAvatar: 'shrink-0',
leadingAvatarSize: '',
content: 'relative text-pretty min-w-0 *:first:mt-0 *:last:mb-0',
actions: [
'opacity-0 group-hover/message:opacity-100 absolute bottom-0 flex items-center',
'transition-opacity'
]
},
variants: {
variant: {
solid: {
content: 'bg-inverted text-inverted'
},
outline: {
content: 'bg-default ring ring-default'
},
soft: {
content: 'bg-elevated/50'
},
subtle: {
content: 'bg-elevated/50 ring ring-default'
},
naked: {
content: ''
}
},
side: {
left: {
container: 'rtl:justify-end'
},
right: {
container: 'ltr:justify-end ms-auto max-w-[75%]'
}
},
leading: {
true: ''
},
actions: {
true: ''
},
compact: {
true: {
root: 'scroll-mt-3',
container: 'gap-1.5 pb-3',
leadingIcon: 'size-5',
leadingAvatarSize: '2xs'
},
false: {
root: 'scroll-mt-4 sm:scroll-mt-6',
container: 'gap-3 pb-8',
leadingIcon: 'size-8',
leadingAvatarSize: 'md'
}
}
},
compoundVariants: [
{
compact: true,
actions: true,
class: {
container: 'pb-8'
}
},
{
leading: true,
compact: false,
side: 'left',
class: {
actions: 'left-11'
}
},
{
leading: true,
compact: true,
side: 'left',
class: {
actions: 'left-6.5'
}
},
{
variant: [
'solid',
'outline',
'soft',
'subtle'
],
compact: false,
class: {
content: 'px-4 py-3 rounded-lg min-h-12',
leading: 'mt-2'
}
},
{
variant: [
'solid',
'outline',
'soft',
'subtle'
],
compact: true,
class: {
content: 'px-2 py-1 rounded-lg min-h-8',
leading: 'mt-1'
}
},
{
variant: 'naked',
side: 'left',
class: {
content: 'w-full'
}
}
],
defaultVariants: {
variant: 'naked'
}
}
}
})
]
})