PXD

Bubble

Show the conversation.

Default

The Evil Rabbit Jumped over the Fence
The Evil Rabbit Jumped over the Fence
<template>
  <PBubble role="system">The Evil Rabbit Jumped over the Fence</PBubble>
  <PBubble role="user">The Evil Rabbit Jumped over the Fence</PBubble>
</template>

Variant

The Evil Rabbit Jumped over the Fence
The Evil Rabbit Jumped over the Fence
<template>
  <PBubble variant="ghost" role="system">The Evil Rabbit Jumped over the Fence</PBubble>
  <PBubble variant="ghost" role="user">The Evil Rabbit Jumped over the Fence</PBubble>
</template>

Loading

<script setup>
import { ref } from 'vue'

const loading = ref(true)
</script>

<template>
  <PToggle v-model="loading" active-label="Loading" />
  <PBubble role="system" :loading="loading">The Evil Rabbit Jumped over the Fence</PBubble>
</template>

Avatar

The Evil Rabbit Jumped over the Fence
The Evil Rabbit Jumped over the Fence
The Evil Rabbit Jumped over the Fence
<template>
  <PBubble role="system" avatar="https://avatars.githubusercontent.com/u/47918504?s=48&v=4">The Evil Rabbit Jumped over the Fence</PBubble>
  <PBubble role="user" avatar="https://avatars.githubusercontent.com/u/47918504?s=48&v=4">The Evil Rabbit Jumped over the Fence</PBubble>
  <PBubble role="user" avatar="https://avatars.githubusercontent.com/u/47918504?s=48&v=4">The Evil Rabbit Jumped over the Fence</PBubble>
</template>
System
The Evil Rabbit Jumped over the Fence
18:30:00
The Evil Rabbit Jumped over the Fence
<script setup>
import RefreshClockwiseIcon from '@gdsicon/vue/refresh-clockwise'
import PencilEditIcon from '@gdsicon/vue/pencil-edit'
</script>

<template>
  <PBubble role="system" header="System">
    The Evil Rabbit Jumped over the Fence

    <template #footer>
      <PButton size="sm" variant="ghost" icon>
        <RefreshClockwiseIcon class="text-gray-900" />
      </PButton>
    </template>
  </PBubble>

  <PBubble role="user">
    The Evil Rabbit Jumped over the Fence

    <template #header>
      18:30:00
    </template>

    <template #footer>
      <PButton size="sm" variant="ghost" icon>
        <PencilEditIcon class="text-gray-900" />
      </PButton>
    </template>
  </PBubble>
</template>

Group

By default, the PBubbleGroup component always shows the latest data at the bottom.

The Evil Rabbit Jumped over the Fence
The Evil Rabbit Jumped over the Fence
<script setup>
import { ref } from 'vue'

const messages = ref([
  { role: 'system', message: 'The Evil Rabbit Jumped over the Fence' },
  { role: 'user', message: 'The Evil Rabbit Jumped over the Fence' },
])

function addMessage() {
  messages.value.push({
    role: Math.random() > 0.5 ? 'system' : 'user',
    message: 'The Evil Rabbit Jumped over the Fence ' + Date.now(),
  })
}
</script>

<template>
  <PButton class="mb-2" @click="addMessage">Add Message</PButton>

  <PBubbleGroup class="max-h-40">
    <PBubble v-for="m of messages" :role="m.role" :text="m.message" />
  </PBubbleGroup>
</template>

Group With Virtual Scroll

Pass items to enable virtual scrolling for large message lists.

The Evil Rabbit Jumped over the Fence 0
The Evil Rabbit Jumped over the Fence 1
The Evil Rabbit Jumped over the Fence 2
The Evil Rabbit Jumped over the Fence 3
The Evil Rabbit Jumped over the Fence 4
The Evil Rabbit Jumped over the Fence 5
The Evil Rabbit Jumped over the Fence 6
The Evil Rabbit Jumped over the Fence 7
The Evil Rabbit Jumped over the Fence 8
The Evil Rabbit Jumped over the Fence 9
The Evil Rabbit Jumped over the Fence 10
The Evil Rabbit Jumped over the Fence 11
The Evil Rabbit Jumped over the Fence 12
The Evil Rabbit Jumped over the Fence 13
The Evil Rabbit Jumped over the Fence 14
The Evil Rabbit Jumped over the Fence 15
The Evil Rabbit Jumped over the Fence 16
The Evil Rabbit Jumped over the Fence 17
The Evil Rabbit Jumped over the Fence 18
The Evil Rabbit Jumped over the Fence 19
The Evil Rabbit Jumped over the Fence 20
The Evil Rabbit Jumped over the Fence 21
The Evil Rabbit Jumped over the Fence 22
The Evil Rabbit Jumped over the Fence 23
The Evil Rabbit Jumped over the Fence 24
The Evil Rabbit Jumped over the Fence 25
The Evil Rabbit Jumped over the Fence 26
The Evil Rabbit Jumped over the Fence 27
The Evil Rabbit Jumped over the Fence 28
The Evil Rabbit Jumped over the Fence 29
The Evil Rabbit Jumped over the Fence 30
The Evil Rabbit Jumped over the Fence 31
The Evil Rabbit Jumped over the Fence 32
The Evil Rabbit Jumped over the Fence 33
The Evil Rabbit Jumped over the Fence 34
The Evil Rabbit Jumped over the Fence 35
The Evil Rabbit Jumped over the Fence 36
The Evil Rabbit Jumped over the Fence 37
The Evil Rabbit Jumped over the Fence 38
The Evil Rabbit Jumped over the Fence 39
The Evil Rabbit Jumped over the Fence 40
The Evil Rabbit Jumped over the Fence 41
The Evil Rabbit Jumped over the Fence 42
The Evil Rabbit Jumped over the Fence 43
The Evil Rabbit Jumped over the Fence 44
The Evil Rabbit Jumped over the Fence 45
The Evil Rabbit Jumped over the Fence 46
The Evil Rabbit Jumped over the Fence 47
The Evil Rabbit Jumped over the Fence 48
The Evil Rabbit Jumped over the Fence 49
<script setup>
import { ref } from 'vue'

const messages = ref(
  Array.from({ length: 50 }, (_, i) => ({
    id: i,
    role: i % 2 === 0 ? 'system' : 'user',
    message: `The Evil Rabbit Jumped over the Fence ${i}`,
  })),
)

function addMessage() {
  messages.value.push({
    id: messages.value.length,
    role: Math.random() > 0.5 ? 'system' : 'user',
    message: 'The Evil Rabbit Jumped over the Fence ' + Date.now(),
  })
}
</script>

<template>
  <PButton class="mb-2" @click="addMessage">Add Message</PButton>

  <PBubbleGroup class="max-h-80" :items="messages" data-key="id">
    <template #item="{ item }">
      <PBubble :role="item.role" :text="item.message" />
    </template>
  </PBubbleGroup>
</template>

Props

NameTypeDefaultDescription
role'user' | 'system' | 'assistant'systemMessage author, user is right-aligned, system and assistant are left-aligned
textstring-Message content rendered when the default slot is empty
headerstring-Text shown above the bubble
avatarstring-Avatar image URL rendered before the bubble, the avatar slot overrides it
loadingboolean-Replace the message content with a spinner
variantdefault | ghostdefaultRender a transparent bubble without border

Slots

NameDescription
defaultDefault slot
reactionsReactions slot

BubbleGroup Props

NameTypeDefaultDescription
itemsany[]-Data array, enables virtual scrolling when provided
data-keystring-Unique key field name for list items
item-sizenumber80Estimated item height in pixels
over-scannumber3Number of items to render beyond the visible area

BubbleGroup Slots

NameDescription
defaultDefault slot (used when items is not provided)
itemScoped slot for virtual scroll mode: { item, index }

Source

Source