
Hello! Tell me more about building AI chatbots with Nuxt UI Pro.
The ChatMessage component renders an <article>
element for a user
or assistant
chat message.
ChatMessages
component to display a list of chat messages.Use the content
prop to display the message content.
<template>
<UChatMessage content="Hello! Tell me more about building AI chatbots with Nuxt UI Pro." />
</template>
Use the side
prop to display the message on the left or right.
<template>
<UChatMessage
side="right"
content="Hello! Tell me more about building AI chatbots with Nuxt UI Pro."
/>
</template>
ChatMessages
component, the side
prop is set to left
for assistant
messages and right
for user
messages.Use the variant
prop to change style of the message.
<template>
<UChatMessage
variant="soft"
content="Hello! Tell me more about building AI chatbots with Nuxt UI Pro."
/>
</template>
ChatMessages
component, the variant
prop is set to naked
for assistant
messages and soft
for user
messages.Use the icon
prop to display an Icon component next to the message.
<template>
<UChatMessage
icon="i-lucide-user"
variant="soft"
side="right"
content="Hello! Tell me more about building AI chatbots with Nuxt UI Pro."
/>
</template>
Use the avatar
prop to display an Avatar component next to the message.
<template>
<UChatMessage
:avatar="{
src: 'https://github.com/benjamincanac.png'
}"
variant="soft"
side="right"
content="Hello! Tell me more about building AI chatbots with Nuxt UI Pro."
/>
</template>
You can also use the avatar.icon
prop to display an icon as the avatar.
<template>
<UChatMessage
:avatar="{
icon: 'i-lucide-bot'
}"
content="Nuxt UI Pro offers several features for building AI chatbots including the ChatMessage, ChatMessages, and ChatPrompt components. Best practices include using the useChat composable from Vercel AI SDK, 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."
/>
</template>
Use the actions
prop to display actions below the message that will be displayed when hovering over the message.
<script setup lang="ts">
const actions = ref([
{
label: 'Copy to clipboard',
icon: 'i-lucide-copy'
}
])
</script>
<template>
<UChatMessage
:actions="actions"
content="Nuxt UI Pro offers several features for building AI chatbots including the ChatMessage, ChatMessages, and ChatPrompt components. Best practices include using the useChat composable from Vercel AI SDK, 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."
/>
</template>
Prop | Default | Type |
---|---|---|
as |
|
|
content |
Text content of the message. Use parts when possible. | |
id |
A unique identifier for the message. | |
role |
The 'data' role is deprecated. | |
icon |
| |
avatar |
| |
variant |
|
|
side |
|
|
data |
For data messages. | |
actions |
Display a list of actions under the message.
The
| |
compact |
|
Render the message in a compact style.
This is done automatically when used inside a |
createdAt |
The timestamp of the message. | |
reasoning |
Reasoning for the message. | |
experimental_attachments |
Additional attachments to be sent along with the message.
| |
annotations |
Additional message-specific information added on the server via StreamData | |
toolInvocations |
Tool invocations (that can be tool calls or tool results, depending on whether or not the invocation has finished) that the assistant made as part of this message.
| |
parts |
The parts of the message. Use this for rendering the message in the UI. Assistant messages can have text, reasoning and tool invocation parts. User messages can have text parts.
| |
ui |
|
Slot | Type |
---|---|
leading |
|
content |
|
actions |
|
export default defineAppConfig({
uiPro: {
chatMessage: {
slots: {
root: 'group/message relative w-full',
container: 'relative flex items-start group-data-[role=user]/message:max-w-[75%]',
leading: 'inline-flex items-center justify-center min-h-6',
leadingIcon: 'shrink-0',
leadingAvatar: 'shrink-0',
leadingAvatarSize: '',
content: 'relative text-pretty',
actions: [
'opacity-0 group-hover/message:opacity-100 absolute bottom-0 flex items-center',
'transition-opacity'
]
},
variants: {
variant: {
solid: {
content: 'bg-(--ui-bg-inverted) text-(--ui-bg)'
},
outline: {
content: 'bg-(--ui-bg) ring ring-(--ui-border)'
},
soft: {
content: 'bg-(--ui-bg-elevated)/50'
},
subtle: {
content: 'bg-(--ui-bg-elevated)/50 ring ring-(--ui-border)'
},
naked: {
content: ''
}
},
side: {
left: {
container: 'rtl:justify-end'
},
right: {
container: 'ltr:justify-end ms-auto'
}
},
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-[calc(var(--ui-radius)*2)] min-h-12',
leading: 'mt-2'
}
},
{
variant: [
'solid',
'outline',
'soft',
'subtle'
],
compact: true,
class: {
content: 'px-2 py-1 rounded-[calc(var(--ui-radius)*2)] min-h-8',
leading: 'mt-1'
}
}
],
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({
uiPro: {
chatMessage: {
slots: {
root: 'group/message relative w-full',
container: 'relative flex items-start group-data-[role=user]/message:max-w-[75%]',
leading: 'inline-flex items-center justify-center min-h-6',
leadingIcon: 'shrink-0',
leadingAvatar: 'shrink-0',
leadingAvatarSize: '',
content: 'relative text-pretty',
actions: [
'opacity-0 group-hover/message:opacity-100 absolute bottom-0 flex items-center',
'transition-opacity'
]
},
variants: {
variant: {
solid: {
content: 'bg-(--ui-bg-inverted) text-(--ui-bg)'
},
outline: {
content: 'bg-(--ui-bg) ring ring-(--ui-border)'
},
soft: {
content: 'bg-(--ui-bg-elevated)/50'
},
subtle: {
content: 'bg-(--ui-bg-elevated)/50 ring ring-(--ui-border)'
},
naked: {
content: ''
}
},
side: {
left: {
container: 'rtl:justify-end'
},
right: {
container: 'ltr:justify-end ms-auto'
}
},
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-[calc(var(--ui-radius)*2)] min-h-12',
leading: 'mt-2'
}
},
{
variant: [
'solid',
'outline',
'soft',
'subtle'
],
compact: true,
class: {
content: 'px-2 py-1 rounded-[calc(var(--ui-radius)*2)] min-h-8',
leading: 'mt-1'
}
}
],
defaultVariants: {
variant: 'naked'
}
}
}
})
]
})
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import uiPro from '@nuxt/ui-pro/vite'
export default defineConfig({
plugins: [
vue(),
uiPro({
uiPro: {
chatMessage: {
slots: {
root: 'group/message relative w-full',
container: 'relative flex items-start group-data-[role=user]/message:max-w-[75%]',
leading: 'inline-flex items-center justify-center min-h-6',
leadingIcon: 'shrink-0',
leadingAvatar: 'shrink-0',
leadingAvatarSize: '',
content: 'relative text-pretty',
actions: [
'opacity-0 group-hover/message:opacity-100 absolute bottom-0 flex items-center',
'transition-opacity'
]
},
variants: {
variant: {
solid: {
content: 'bg-(--ui-bg-inverted) text-(--ui-bg)'
},
outline: {
content: 'bg-(--ui-bg) ring ring-(--ui-border)'
},
soft: {
content: 'bg-(--ui-bg-elevated)/50'
},
subtle: {
content: 'bg-(--ui-bg-elevated)/50 ring ring-(--ui-border)'
},
naked: {
content: ''
}
},
side: {
left: {
container: 'rtl:justify-end'
},
right: {
container: 'ltr:justify-end ms-auto'
}
},
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-[calc(var(--ui-radius)*2)] min-h-12',
leading: 'mt-2'
}
},
{
variant: [
'solid',
'outline',
'soft',
'subtle'
],
compact: true,
class: {
content: 'px-2 py-1 rounded-[calc(var(--ui-radius)*2)] min-h-8',
leading: 'mt-1'
}
}
],
defaultVariants: {
variant: 'naked'
}
}
}
})
]
})