165

Message

PreviousNext

Composable message components with avatar, content variants, and automatic styling for user and assistant messages.

How do I create an agent?

<script setup lang="ts">
import { Message, MessageContent } from '@/components/elevenlabs-ui/message'
import { Orb } from '@/components/elevenlabs-ui/orb'
import { Response } from '@/components/elevenlabs-ui/response'
import { onMounted, onUnmounted, ref } from 'vue'

const assistantMessageTokens = [
  'To',
  ' create',
  ' a',
  ' new',
  ' agent',
  ' with',
  ' **',
  'ElevenLabs',
  ' Agents',
  '**',
  ',',
  ' head',
  ' to',
  ' this',
  ' link',
  ':',
  ' ',
  '[',
  'https://elevenlabs.io/app/agents',
  '](',
  'https://elevenlabs.io/app/agents',
  ')',
  '.',
  '\n\n',
  '1.',
  ' Sign',
  ' in',
  ' to',
  ' your',
  ' ElevenLabs',
  ' account',
  '.',
  '\n',
  '2.',
  ' Click',
  ' **New',
  ' Agent**',
  ' to',
  ' start',
  '.',
  '\n',
  '3.',
  ' Give',
  ' your',
  ' agent',
  ' a',
  ' name',
  ' and',
  ' description',
  '.',
  '\n',
  '4.',
  ' Configure',
  ' its',
  ' behavior',
  ',',
  ' knowledge',
  ' sources',
  ',',
  ' and',
  ' voice',
  '.',
  '\n',
  '5.',
  ' Save',
  ' it',
  ' —',
  ' and',
  ' your',
  ' agent',
  ' is',
  ' ready',
  ' to',
  ' use',
  '.',
]

const content = ref('\u200B')
const isStreaming = ref(false)

let intervalId: ReturnType<typeof setInterval>
let timeoutId: ReturnType<typeof setTimeout>

onMounted(() => {
  let currentContent = ''
  let index = 0

  // Equivalent to the 500ms delay before "talking" state
  timeoutId = setTimeout(() => {
    isStreaming.value = true
  }, 500)

  // Streaming interval logic
  intervalId = setInterval(() => {
    if (index < assistantMessageTokens.length) {
      currentContent += assistantMessageTokens[index]
      content.value = currentContent
      index++
    }
    else {
      clearInterval(intervalId)
      isStreaming.value = false
    }
  }, 100)
})

onUnmounted(() => {
  if (intervalId)
    clearInterval(intervalId)
  if (timeoutId)
    clearTimeout(timeoutId)
})
</script>

<template>
  <div class="flex h-full max-h-[400px] w-full max-w-2xl flex-col overflow-hidden">
    <div class="flex flex-col gap-4 overflow-y-auto px-4 py-4">
      <div class="shrink-0">
        <Message from="user">
          <MessageContent>
            How do I create an agent?

            <!-- <Response :content="'How do I create an agent?'" /> -->
          </MessageContent>
        </Message>
      </div>

      <div class="message-demo-lists shrink-0">
        <Message from="assistant">
          <MessageContent>
            <Response :content="content" />
          </MessageContent>

          <div class="ring-border size-8 overflow-hidden rounded-full ring-1">
            <Orb
              class="h-full w-full"
              :agent-state="isStreaming ? 'talking' : null"
            />
          </div>
        </Message>
      </div>
    </div>
  </div>
</template>

<style scoped>
/* Scoped styles replace the 'style jsx global' logic */
:deep(.message-demo-lists ol),
:deep(.message-demo-lists ul) {
  padding-left: 1.25rem !important;
}

:deep(.message-demo-lists li) {
  margin-left: 0 !important;
}
</style>

Installation

pnpm dlx elevenlabs-ui-vue@latest add message

Usage

import { Message, MessageAvatar, MessageContent } from "@/components/elevenlabs-ui/message"

Basic Message

<template>
  <Message from="user">
    <MessageAvatar src="/user-avatar.jpg" name="John" />
    <MessageContent>
      Hello, how can I help you?
    </MessageContent>
  </Message>

  <Message from="assistant">
    <MessageAvatar src="/assistant-avatar.jpg" name="AI" />
    <MessageContent>
      I'm here to assist you with any questions!
    </MessageContent>
  </Message>
</template>

Message Variants

The MessageContent component supports two variants:

<script setup lang="ts">
import { Message, MessageAvatar, MessageContent } from "@/components/elevenlabs-ui/message"
</script>

<template>
<!-- Contained variant - default, has background and padding -->
  <Message from="user">
    <MessageAvatar src="/user-avatar.jpg" />
    <MessageContent variant="contained">
      This is a contained message with background
    </MessageContent>
  </Message>

  <!-- Flat variant - no background for assistant, minimal styling -->
  <Message from="assistant">
    <MessageAvatar src="/assistant-avatar.jpg" />
    <MessageContent variant="flat">
      This is a flat message with minimal styling
    </MessageContent>
  </Message>
</template>

In a Conversation

<script>
  import { Conversation, ConversationContent } from "@/components/elevenlabs-ui/conversation"
  import { Message, MessageAvatar, MessageContent } from "@/components/elevenlabs-ui/message"
</script>

<template>
<Conversation>
  <ConversationContent>
    <Message
      v-for="message in messages"
      :key="message.id"
      :from="message.from"
    >
      <MessageAvatar
        :src="message.avatarUrl"
        :name="message.name"
      />
      <MessageContent>
        {{ message.content }}
      </MessageContent>
    </Message>
  </ConversationContent>
</Conversation>
</template>

API Reference

Message

The main container component that handles layout and alignment based on message sender.

Props

PropTypeDescription
from"user" | "assistant"Required. Determines alignment and styling
classstringOptional CSS classes
...propsHTMLAttributesAll standard div element props

MessageContent

Container for message text and content with variant styling.

Props

PropTypeDescription
variant"contained" | "flat"Visual style variant (default: "contained")
classstringOptional CSS classes
...propsHTMLAttributesAll standard div element props

MessageAvatar

Avatar component for displaying user or assistant profile images.

Props

PropTypeDescription
srcstringRequired. Avatar image URL
namestringName for fallback (shows first 2 chars if no image)
classstringOptional CSS classes
...propsAvatarPropsAll standard Avatar component props

Notes

  • Uses CSS group selectors for context-aware styling based on from prop
  • User messages align to the right, assistant messages to the left
  • Contained variant provides background colors that differ for user/assistant
  • Flat variant is useful for assistant messages in a minimal design
  • Avatar has a subtle ring border and fallback text support
  • Works seamlessly with the Conversation component
  • This component is inspired by Vercel's AI SDK Message component with modifications for ElevenLabs UI