Usage 2.2+
The ChatMessages component displays a list of ChatMessage components using either the default slot or the messages prop.
<template>
<B24ChatMessages>
<B24ChatMessage
v-for="(message, index) in messages"
:key="index"
v-bind="message"
/>
</B24ChatMessages>
</template>
- Initial scroll to the bottom upon loading (
shouldScrollToBottom). - Continuous scrolling down as new messages arrive (
shouldAutoScroll). - An "Auto scroll" button appears when scrolled up, allowing users to jump back to the latest messages (
autoScroll). - A loading indicator displays while the assistant is processing (
status). - Submitted messages are scrolled to the top of the viewport and the height of the last user message is dynamically adjusted.
Messages
Use the messages prop to display a list of chat messages.
{
"wait": "Loading client-side content..."
}Status
Use the status prop to display a visual indicator when the assistant is processing.
{
"wait": "Loading client-side content..."
}submitted: The message has been sent to the API and we're awaiting the start of the response stream.streaming: The response is actively streaming in from the API, receiving chunks of data.ready: The full response has been received and processed; a new user message can be submitted.error: An error occurred during the API request, preventing successful completion.
User
Use the user prop to change the ChatMessage props for user messages. Defaults to:
side: 'right'variant: 'message'
{
"wait": "Loading client-side content..."
}Assistant
Use the assistant prop to change the ChatMessage props for assistant messages. Defaults to:
side: 'left'variant: 'message'
{
"wait": "Loading client-side content..."
}Auto Scroll
Use the auto-scroll prop to customize or hide the auto scroll button (with false value) displayed when scrolling to the top of the chat. Defaults to:
color: 'air-secondary-no-accent'
You can pass any property from the Button component to customize it.
{
"wait": "Loading client-side content..."
}Auto Scroll Icon
Use the auto-scroll-icon prop to customize the auto scroll button Icon.
{
"wait": "Loading client-side content..."
}Should Auto Scroll
Use the should-auto-scroll prop to enable/disable continuous auto scroll while messages are streaming. Defaults to false.
<template>
<B24ChatMessages :messages="messages" should-auto-scroll />
</template>
Should Scroll To Bottom
Use the should-scroll-to-bottom prop to enable/disable bottom auto scroll when the component is mounted. Defaults to true.
<template>
<B24ChatMessages :messages="messages" :should-scroll-to-bottom="false" />
</template>
Examples
Within a page
Use the ChatMessages component with the Chat class from AI SDK v5 to display a list of chat messages within a page.
Pass the messages prop alongside the status prop that will be used for the auto scroll and the indicator display.
<script setup lang="ts">
import { Chat } from '@ai-sdk/vue'
import { getTextFromMessage } from '@bitrix24/b24ui-nuxt/utils/ai'
const input = ref('')
const chat = new Chat({
onError(error) {
console.error(error)
}
})
function onSubmit() {
chat.sendMessage({ text: input.value })
input.value = ''
}
</script>
<template>
<B24Card>
<B24Container>
<B24ChatMessages :messages="chat.messages" :status="chat.status">
<template #content="{ message }">
<MDC :value="getTextFromMessage(message)" :cache-key="message.id" class="*:first:mt-0 *:last:mb-0" />
</template>
</B24ChatMessages>
</B24Container>
<template #footer>
<B24Container class="pb-4 sm:pb-6">
<B24ChatPrompt v-model="input" :error="chat.error" @submit="onSubmit">
<B24ChatPromptSubmit :status="chat.status" @stop="chat.stop()" @reload="chat.regenerate()" />
</B24ChatPrompt>
</B24Container>
</template>
</B24Card>
</template>
MDC component from @nuxtjs/mdc to render the content of the message. The getTextFromMessage utility extracts the text content from the AI SDK V5 message parts. As Bitrix24 UI provides pre-styled prose components, your content will be automatically styled.With indicator slot
You can customize the loading indicator that appears when the status is submitted.
API
Props
Slots
ChatMessage component inside ChatMessages, they are automatically forwarded allowing you to customize individual messages when using the messages prop.<script setup lang="ts">
import { getTextFromMessage } from '@bitrix24/b24ui-nuxt/utils/ai'
</script>
<template>
<B24ChatMessages :messages="messages" :status="status">
<template #content="{ message }">
<MDC :value="getTextFromMessage(message)" :cache-key="message.id" class="*:first:mt-0 *:last:mb-0" />
</template>
</B24ChatMessages>
</template>
Theme
export default defineAppConfig({
b24ui: {
chatMessages: {
slots: {
root: 'w-full flex flex-col gap-1 flex-1 px-2.5 [&>article]:last-of-type:min-h-(--last-message-height)',
indicator: 'h-6 flex items-center gap-1 py-3 *:size-2 *:rounded-full *:bg-(--ui-color-base-7) [&>*:nth-child(1)]:animate-[bounce_1s_infinite] [&>*:nth-child(2)]:animate-[bounce_1s_0.15s_infinite] [&>*:nth-child(3)]:animate-[bounce_1s_0.3s_infinite]',
viewport: 'absolute inset-x-0 top-[86%] data-[state=open]:animate-[fade-in_200ms_ease-out] data-[state=closed]:animate-[fade-out_200ms_ease-in]',
autoScroll: 'rounded-full absolute right-1/2 translate-x-1/2 bottom-0'
},
variants: {
compact: {
true: '',
false: ''
}
}
}
}
})
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import bitrix24UIPluginVite from '@bitrix24/b24ui-nuxt/vite'
export default defineConfig({
plugins: [
vue(),
bitrix24UIPluginVite({
b24ui: {
chatMessages: {
slots: {
root: 'w-full flex flex-col gap-1 flex-1 px-2.5 [&>article]:last-of-type:min-h-(--last-message-height)',
indicator: 'h-6 flex items-center gap-1 py-3 *:size-2 *:rounded-full *:bg-(--ui-color-base-7) [&>*:nth-child(1)]:animate-[bounce_1s_infinite] [&>*:nth-child(2)]:animate-[bounce_1s_0.15s_infinite] [&>*:nth-child(3)]:animate-[bounce_1s_0.3s_infinite]',
viewport: 'absolute inset-x-0 top-[86%] data-[state=open]:animate-[fade-in_200ms_ease-out] data-[state=closed]:animate-[fade-out_200ms_ease-in]',
autoScroll: 'rounded-full absolute right-1/2 translate-x-1/2 bottom-0'
},
variants: {
compact: {
true: '',
false: ''
}
}
}
}
})
]
})