ChatMessage

GitHub
Display a chat message with icon, avatar, and actions.

Usage

The ChatMessage component renders an <article> element for a user or assistant chat message.

Hello! Tell me more about building AI chatbots with Pohon UI.
Use the ChatMessages component to display a list of chat messages.

Parts

Use the parts prop to display the message content using the AI SDK format.

Hello! Tell me more about building AI chatbots with Pohon UI.
<template>
  <PChatMessage
    :parts="[
      {
        type: 'text',
        id: '1',
        text: 'Hello! Tell me more about building AI chatbots with Pohon UI.'
      }
    ]"
    role="user"
    id="1"
  />
</template>
The parts prop is the recommended format for the AI SDK. Each part has a type (e.g. 'text') and corresponding content. The ChatMessage component also supports the deprecated content prop for backward compatibility.

Side

Use the side prop to display the message on the left or right.

Hello! Tell me more about building AI chatbots with Pohon UI.
<template>
  <PChatMessage
    side="right"
    :parts="[
      {
        type: 'text',
        id: '1',
        text: 'Hello! Tell me more about building AI chatbots with Pohon UI.'
      }
    ]"
    role="user"
    id="1"
  />
</template>
When using the ChatMessages component, the side prop is set to left for assistant messages and right for user messages.

Variant

Use the variant prop to change style of the message.

Hello! Tell me more about building AI chatbots with Pohon UI.
<template>
  <PChatMessage
    variant="soft"
    :parts="[
      {
        type: 'text',
        id: '1',
        text: 'Hello! Tell me more about building AI chatbots with Pohon UI.'
      }
    ]"
    role="user"
    id="1"
  />
</template>
When using the ChatMessages component, the variant prop is set to naked for assistant messages and soft for user messages.

Color

Use the color prop to change the color of the message.

Hello! Tell me more about building AI chatbots with Pohon UI.
<template>
  <PChatMessage
    variant="soft"
    color="primary"
    :parts="[
      {
        type: 'text',
        id: '1',
        text: 'Hello! Tell me more about building AI chatbots with Pohon UI.'
      }
    ]"
    role="user"
    id="1"
  />
</template>

Icon

Use the icon prop to display an Icon component next to the message.

Hello! Tell me more about building AI chatbots with Pohon UI.
<template>
  <PChatMessage
    icon="i-lucide-user"
    variant="soft"
    side="right"
    :parts="[
      {
        type: 'text',
        id: '1',
        text: 'Hello! Tell me more about building AI chatbots with Pohon UI.'
      }
    ]"
    role="user"
    id="1"
  />
</template>

Avatar

Use the avatar prop to display an Avatar component next to the message.

Hello! Tell me more about building AI chatbots with Pohon UI.
<template>
  <PChatMessage
    :avatar="{
      src: 'https://github.com/benjamincanac.png',
      loading: 'lazy'
    }"
    variant="soft"
    side="right"
    :parts="[
      {
        type: 'text',
        id: '1',
        text: 'Hello! Tell me more about building AI chatbots with Pohon UI.'
      }
    ]"
    role="user"
    id="1"
  />
</template>

You can also use the avatar.icon prop to display an icon as the avatar.

Pohon 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, 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>
  <PChatMessage
    :avatar="{
      icon: 'i-lucide-bot'
    }"
    :parts="[
      {
        type: 'text',
        id: '1',
        text: 'Pohon 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, 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

Use the actions prop to display actions below the message that will be displayed when hovering over the message.

Pohon 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, 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.
<script setup lang="ts">
import type { ButtonProps } from 'pohon-ui'

const actions = ref<ButtonProps[]>([
  {
    label: 'Copy to clipboard',
    icon: 'i-lucide-copy'
  }
])
</script>

<template>
  <PChatMessage
    :actions="actions"
    :parts="[
      {
        type: 'text',
        id: '1',
        text: 'Pohon 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, 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>
<script setup lang="ts">
import { ref } from 'vue'
import type { ButtonProps } from 'pohon-ui'

const actions = ref<ButtonProps[]>([
  {
    label: 'Copy to clipboard',
    icon: 'i-lucide-copy'
  }
])
</script>

<template>
  <PChatMessage
    :actions="actions"
    :parts="[
      {
        type: 'text',
        id: '1',
        text: 'Pohon 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, 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>

Examples

Check the Chat overview page for installation instructions, server setup and usage examples.

API

Props

Prop Default Type

Slots

Slot Type

Theme

app.config.ts
export default defineAppConfig({
  ui: {
    chatMessage: {
      slots: {
        root: 'group/message relative w-full',
        header: 'flex mb-1.5',
        container: 'relative flex items-start',
        body: 'min-w-0',
        leading: 'inline-flex items-center justify-center min-h-6',
        leadingIcon: 'shrink-0',
        leadingAvatar: 'shrink-0',
        leadingAvatarSize: '',
        files: 'flex flex-wrap items-center gap-1.5',
        content: 'relative text-pretty wrap-break-word *:first:mt-0 *:last:mb-0',
        actions: [
          'flex items-center bottom-0 absolute [@media(hover:hover)]:opacity-0 group-hover/message:opacity-100 focus-within:opacity-100',
          'transition-opacity ease-out'
        ]
      },
      variants: {
        variant: {
          solid: '',
          outline: '',
          soft: '',
          subtle: '',
          naked: ''
        },
        color: {
          primary: '',
          secondary: '',
          success: '',
          info: '',
          warning: '',
          error: '',
          neutral: ''
        },
        side: {
          left: {},
          right: {
            container: 'justify-end ms-auto max-w-[75%]',
            header: 'justify-end',
            actions: 'end-0'
          }
        },
        leading: {
          true: ''
        },
        actions: {
          true: ''
        },
        compact: {
          true: {
            root: 'scroll-mt-3',
            container: 'gap-1.5 pb-3',
            content: 'space-y-2',
            leadingIcon: 'size-5',
            leadingAvatarSize: '2xs'
          },
          false: {
            root: 'scroll-mt-4 sm:scroll-mt-6',
            container: 'gap-3 pb-8',
            content: 'space-y-4',
            leadingIcon: 'size-8',
            leadingAvatarSize: 'md'
          }
        }
      },
      compoundVariants: [
        {
          compact: true,
          actions: true,
          class: {
            container: 'pb-8'
          }
        },
        {
          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: {
            body: 'w-full',
            content: 'w-full'
          }
        },
        {
          color: 'primary',
          variant: 'solid',
          class: {
            content: 'bg-primary color-primary-foreground'
          }
        },
        {
          color: 'primary',
          variant: 'outline',
          class: {
            content: 'color-primary ring ring-primary/25'
          }
        },
        {
          color: 'primary',
          variant: 'soft',
          class: {
            content: 'bg-primary/10 color-primary'
          }
        },
        {
          color: 'primary',
          variant: 'subtle',
          class: {
            content: 'bg-primary/10 color-primary ring ring-primary/25'
          }
        },
        {
          color: 'primary',
          variant: 'naked',
          class: {
            content: 'color-primary'
          }
        },
        {
          color: 'neutral',
          variant: 'solid',
          class: {
            content: 'bg-background-inverted color-text-inverted'
          }
        },
        {
          color: 'neutral',
          variant: 'outline',
          class: {
            content: 'bg-background ring ring-border'
          }
        },
        {
          color: 'neutral',
          variant: 'soft',
          class: {
            content: 'bg-background-elevated/50'
          }
        },
        {
          color: 'neutral',
          variant: 'subtle',
          class: {
            content: 'bg-background-elevated/50 ring ring-border'
          }
        }
      ],
      defaultVariants: {
        side: 'left',
        variant: 'naked',
        color: 'neutral'
      }
    }
  }
})
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from 'pohon-ui/vite'

export default defineConfig({
  plugins: [
    vue(),
    ui({
      ui: {
        chatMessage: {
          slots: {
            root: 'group/message relative w-full',
            header: 'flex mb-1.5',
            container: 'relative flex items-start',
            body: 'min-w-0',
            leading: 'inline-flex items-center justify-center min-h-6',
            leadingIcon: 'shrink-0',
            leadingAvatar: 'shrink-0',
            leadingAvatarSize: '',
            files: 'flex flex-wrap items-center gap-1.5',
            content: 'relative text-pretty wrap-break-word *:first:mt-0 *:last:mb-0',
            actions: [
              'flex items-center bottom-0 absolute [@media(hover:hover)]:opacity-0 group-hover/message:opacity-100 focus-within:opacity-100',
              'transition-opacity ease-out'
            ]
          },
          variants: {
            variant: {
              solid: '',
              outline: '',
              soft: '',
              subtle: '',
              naked: ''
            },
            color: {
              primary: '',
              secondary: '',
              success: '',
              info: '',
              warning: '',
              error: '',
              neutral: ''
            },
            side: {
              left: {},
              right: {
                container: 'justify-end ms-auto max-w-[75%]',
                header: 'justify-end',
                actions: 'end-0'
              }
            },
            leading: {
              true: ''
            },
            actions: {
              true: ''
            },
            compact: {
              true: {
                root: 'scroll-mt-3',
                container: 'gap-1.5 pb-3',
                content: 'space-y-2',
                leadingIcon: 'size-5',
                leadingAvatarSize: '2xs'
              },
              false: {
                root: 'scroll-mt-4 sm:scroll-mt-6',
                container: 'gap-3 pb-8',
                content: 'space-y-4',
                leadingIcon: 'size-8',
                leadingAvatarSize: 'md'
              }
            }
          },
          compoundVariants: [
            {
              compact: true,
              actions: true,
              class: {
                container: 'pb-8'
              }
            },
            {
              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: {
                body: 'w-full',
                content: 'w-full'
              }
            },
            {
              color: 'primary',
              variant: 'solid',
              class: {
                content: 'bg-primary color-primary-foreground'
              }
            },
            {
              color: 'primary',
              variant: 'outline',
              class: {
                content: 'color-primary ring ring-primary/25'
              }
            },
            {
              color: 'primary',
              variant: 'soft',
              class: {
                content: 'bg-primary/10 color-primary'
              }
            },
            {
              color: 'primary',
              variant: 'subtle',
              class: {
                content: 'bg-primary/10 color-primary ring ring-primary/25'
              }
            },
            {
              color: 'primary',
              variant: 'naked',
              class: {
                content: 'color-primary'
              }
            },
            {
              color: 'neutral',
              variant: 'solid',
              class: {
                content: 'bg-background-inverted color-text-inverted'
              }
            },
            {
              color: 'neutral',
              variant: 'outline',
              class: {
                content: 'bg-background ring ring-border'
              }
            },
            {
              color: 'neutral',
              variant: 'soft',
              class: {
                content: 'bg-background-elevated/50'
              }
            },
            {
              color: 'neutral',
              variant: 'subtle',
              class: {
                content: 'bg-background-elevated/50 ring ring-border'
              }
            }
          ],
          defaultVariants: {
            side: 'left',
            variant: 'naked',
            color: 'neutral'
          }
        }
      }
    })
  ]
})
Some colors in compoundVariants are omitted for readability. Check out the source code on GitHub.

Changelog

No recent changes