Skip to content

BubbleList

使用import { BubbleList } from 'vue-element-plus-x'
文档
Edit this pageChangelogFeedback

Introduction

BubbleList is built on the Bubble component and is used to display a list of chat bubbles. It has built-in virtual scrolling (virtua/vue), auto-follow-to-bottom, scroll state machine, unread count, bidirectional pagination loading, back-to-bottom button, and mixed node rendering — all out of the box, configure as needed.

Code Examples

Basic Usage

Quickly render a group of chat bubbles via the list array. Each object in the array is passed through to the built-in Bubble component — all Bubble properties (content, placement, loading, shape, variant, etc.) can be configured directly. Adding, removing, or modifying messages only requires maintaining this array.

💡 Tip

Control the list height via the max-height property or the parent container's height — a scrollbar appears automatically when content overflows. See Bubble docs for detailed item properties.

Scroll Control Methods

iV2 auto-scroll rules: When autoScroll is on (default), appending messages auto-scrolls to bottom and unread count stays 0.
To experience unread badge + back-to-bottom button, first turn off autoScroll below, then manually scroll up and append messages — the view stays still, unread +1, and the back-to-bottom button appears. This is the core V2 state machine experience.
autoScroll:
On (auto-scroll to bottom)
Scroll StateAT_BOTTOM
Unread Count0
Total Messages0
Target Index0

Precisely control scroll position via three component instance methods: scrollToTop(), scrollToBottom(), scrollToBubble(index) — all support a smooth parameter for smooth scrolling.

Also exposes currentScrollState and currentUnreadCount instance properties. You can also listen to @scroll-state-change / @unread-count-change events for real-time state awareness (AT_BOTTOM / SCROLLED_UP / HAS_NEW_MESSAGES).

Auto Scroll Control

⚙️AutoScroll Control Panel
autoScrollEnabled — New messages auto-scroll to bottom
ON
Current mode: Auto-follow
All new messages (user / AI) will automatically scroll to the bottom, unread count stays 0. Try scrolling up and then appending a message to see if it still auto-scrolls to bottom.
scrollStateAT_BOTTOM
unreadCount0
autoScrollON

autoScroll (default true) controls whether new messages automatically scroll to the bottom. When disabled, new messages accumulate unread count instead — this is a prerequisite for showing unread badges.

Special Behavior for Streaming Output

Even when autoScroll is enabled, streaming increments only follow when the user is at the bottom; scrolling up won't force a jump back, avoiding reading interruption.

Back to Bottom Button

Core Controls
autoScrollEnabled — new messages auto-scroll to bottom, no unread
On
Custom slot (V2)
Default button
Scrollbar display
On hover
Built-in Button Style
Loading animation
On
Button color
Icon size
Button Position Also applies in slot mode
Bottom %
20%
Horizontal %
50%
autoScroll is ON
After appending messages, the list auto-scrolls to the bottom. unreadCount stays 0 and the back-to-bottom button won't appear.
Try: scroll up a bit first, then click "+ User Message" to see if it still auto-scrolls back.
scrollStateAT_BOTTOM
unreadCount0
autoScrollON
Button ModeBuilt-in Default

Built-in back-to-bottom button with configurable appearance, or fully customize it with the #backToBottom slot.

Adjust button behavior and style via showBackButton, backButtonThreshold, backButtonPosition, btnColor / btnIconSize / btnLoading, etc. When autoScroll is off, the button automatically shows an unread badge — the slot context provides unreadCount (current unread count) and scrollToBottom() (clears unread on call).

Streaming Follow

~Core Experience Flow: ① Click "Start Streaming" → ② Wait for AI output → ③ Scroll up to interrupt → ④ Observe unread count increase, list stops jumping → ⑤ Click "Return to Bottom" → ⑥ Observe subsequent chunks auto-follow
Scroll StateAT_BOTTOM
Unread Count0
Stream StatusIdle
Current Round0
Chars Emitted0/0
Running Tick0/120
Last ActionClick "Start Streaming" then scroll up to observe follow interruption; scroll back to bottom to observe auto-resume.

When autoScroll is enabled (default), content height changes during streaming output will automatically follow to the bottom. After the user scrolls up, following is interrupted; scrolling back to the bottom resumes automatically — no extra configuration needed.

Custom Follow Strategy

For custom follow logic (e.g., only force follow for own messages), use the shouldFollowContent callback to take over decision making. The reason field in the callback parameter indicates the trigger source: own-message (own send), streaming (streaming increment), new-message (newly appended message).

Bidirectional Pagination Loading

First scroll up to the top to trigger history loading, then scroll down to the bottom to trigger more messages. Observe the boundary status area switching between loading → no-more.
Scroll StateAT_BOTTOM
Unread Count0
Top Triggers0
Bottom Triggers0
History Batches0/3
Bottom Batches0/2
Last ActionScroll to the top manually to trigger history loading; scroll back to the bottom and continue scrolling down to load more messages. Top loading: No, Bottom loading: No

Scrolling up to the top triggers @load-more-top; scrolling down to the bottom triggers @load-more-bottom. After data is ready, call loadMoreTopComplete() / loadMoreBottomComplete() to notify the component — scroll position is automatically corrected with no manual jump handling needed.

Use topStatus / bottomStatus props ({ type, text }) to control the boundary status display (loading / no-more), combined with #topStatus / #bottomStatus slots for custom UI.

Mixed Nodes

Mixed Nodes / Unified Item Slot

Regular messages continue using the default Bubble renderer; when an item contains a special identifier, it goes through the unified #item slot. This demo shows date nodes, history-divider nodes, and system-tip nodes coexisting on the same timeline.

Scroll StateAT_BOTTOM
Unread Count0
Node Count0

In addition to bubble messages, the list can contain arbitrary node types (date dividers, system tips, history-load markers, etc.). Mark non-bubble nodes via the itemType property or a resolver function — matched items render through the #item slot while normal messages still use the default Bubble.

The slot context { item, index, itemType } distinguishes node types for different UI rendering. Special node heights are automatically measured in virtual scroll.

Slot Customization

Dynamic content setting
Custom loading

Fully take over list rendering with 9 slots: #avatar, #header, #content, #footer, #loading control each bubble's parts; #backToBottom customizes the back-to-bottom button (with unread badge); #topStatus / #bottomStatus customize boundary status areas; #item renders non-bubble type nodes.

Theme Overrides

Override BubbleList theme variables via ConfigProvider.themeOverrides. See the full variable list and copyable template:

Scroll the list and observe max-height and back-button size changes.
Message 1: used to demonstrate scrolling and the back button.
Message 2: used to demonstrate scrolling and the back button.
Message 3: used to demonstrate scrolling and the back button.
Message 4: used to demonstrate scrolling and the back button.
Message 5: used to demonstrate scrolling and the back button.
Message 6: used to demonstrate scrolling and the back button.
Message 7: used to demonstrate scrolling and the back button.
Message 8: used to demonstrate scrolling and the back button.
Message 9: used to demonstrate scrolling and the back button.
Message 10: used to demonstrate scrolling and the back button.
Message 11: used to demonstrate scrolling and the back button.
Message 12: used to demonstrate scrolling and the back button.
Message 13: used to demonstrate scrolling and the back button.
Message 14: used to demonstrate scrolling and the back button.
Message 15: used to demonstrate scrolling and the back button.
Message 16: used to demonstrate scrolling and the back button.
Message 17: used to demonstrate scrolling and the back button.
Message 18: used to demonstrate scrolling and the back button.

Override BubbleList --elx-* variables via ConfigProvider.themeOverrides and also style Bubble for a stronger contrast.

Using with x-markdown-vue

Starting from v2.0.0, the component library no longer bundles XMarkdown / XMarkdownAsync. For Markdown rendering, use the standalone package x-markdown-vue, or see the dedicated docs: XMarkdown.

Installation

bash
pnpm add x-markdown-vue
pnpm add katex
pnpm add shiki shiki-stream

💡 Tip

If you need code block syntax highlighting, please install shiki and shiki-stream. Otherwise, you may see this error in the console: Streaming highlighter initialization failed: Error: Failed to load shiki-stream module

Basic Usage

Click "Start Streaming Markdown" first, then try scrolling up to interrupt following, then click "Scroll to Bottom" to observe auto-resume.
Scroll StateAT_BOTTOM
Unread Count0
Stream StatusIdle
Chars Emitted0/0
Current Round0
Last ActionClick "Start Streaming Markdown" to observe AI messages rendering incrementally with scroll following.

Supports list rendering with formulas, code blocks, and task lists, and simulates real-time AI streaming Markdown output.

V2 Upgrade Notes

  • Streaming Follow: V2 automatically sticks to the bottom during streaming output (as content grows taller). When the user scrolls up, following is interrupted; returning to the bottom resumes it automatically. V1 required manual scroll management.
  • Virtual Scroll Compatibility: V2 virtual scroll + dynamic height measurement automatically re-measures item height when streaming content grows, preventing scroll position jumps.
  • State Awareness: The scroll-state-change and unread-count-change events let you track scroll state changes in real time during streaming output.

Fog Effect

By setting the enable-animate property, you can achieve a typewriter fog effect:

vue
<script setup>
import { ref } from 'vue';
import { BubbleList } from 'vue-element-plus-x';
import { MarkdownRenderer } from 'x-markdown-vue';
import 'x-markdown-vue/style';

const list = ref([
  { content: '', placement: 'start' } // Streaming content will be updated dynamically
]);
</script>

<template>
  <BubbleList :list="list">
    <template #content="{ item }">
      <MarkdownRenderer :markdown="item.content" :enable-animate="true" />
    </template>
  </BubbleList>
</template>

Props

NameTypeRequiredDefaultDescription
listArrayYes-Message array. Each object is passed through to the built-in Bubble component and supports all Bubble props.
autoScrollBooleanNotrueWhether to auto-scroll to the bottom when new messages are added. When disabled, new messages accumulate as unread count.
maxHeightStringNo-Maximum list height. Defaults to filling the parent container.
virtualBooleanNotrueWhether to enable virtual scrolling (based on virtua/vue). Recommended to keep on for large datasets.
smoothScrollBooleanNofalseWhether programmatic scrolling uses smooth animation by default.
itemKeystring | FunctionNo'key'Unique node identifier. Can be a field name or (item, index) => key function.
itemTypestring | FunctionNo-Non-bubble node type identifier. When matched, renders via the #item slot. Can be a field name or function.
showBackButtonBooleanNotrueWhether to show the back-to-bottom button.
backButtonThresholdNumberNo80Threshold (px from bottom) to trigger showing the back-to-bottom button.
backButtonPositionObjectNo{ bottom: '20px', left: 'calc(50% - 19px)' }CSS positioning of the back-to-bottom button. Supports top / right / bottom / left / transform.
backButtonSmoothScrollBooleanNotrueWhether clicking the back-to-bottom button uses smooth scrolling.
alwaysShowScrollbarBooleanNofalseWhether to always show the scrollbar.
btnLoadingBooleanNotrueWhether to show loading state on the built-in back-to-bottom button.
btnColorStringNo'#409EFF'Color of the built-in back-to-bottom button.
btnIconSizeNumberNo24Icon size (px) of the built-in back-to-bottom button.
topStatus{ type, text? }No-Top boundary status. type can be idle / loading / no-more / error.
bottomStatus{ type, text? }No-Bottom boundary status, same as topStatus.
loadMoreTopThresholdNumberNo100Distance from top (px) to trigger @load-more-top.
loadMoreBottomThresholdNumberNo100Distance from bottom (px) to trigger @load-more-bottom.
shouldFollowContentFunctionNo-Custom content follow strategy. Return true to scroll to bottom, false to accumulate unread. Callback params include reason / item / index / scrollState / unreadCount / autoScroll.

Events

Event NameParametersDescription
@load-more-top-Triggered when scrolling up reaches the threshold. Load history here.
@load-more-bottom-Triggered when scrolling down reaches the threshold. Load more here.
@scroll-state-change(state: 'AT_BOTTOM' | 'SCROLLED_UP' | 'HAS_NEW_MESSAGES')Triggered when scroll state changes.
@unread-count-change(count: number)Triggered when unread count changes.

Ref Instance Methods

Method / PropertySignatureDescription
scrollToTop(smooth?: boolean) => voidScroll to the top. smooth controls animation (defaults to the smoothScroll prop).
scrollToBottom(smooth?: boolean) => voidScroll to the bottom, resets unread count and state machine.
scrollToBubble(index: number, smooth?: boolean) => voidScroll to the message at the specified index.
loadMoreTopComplete() => voidCall after top data finishes loading. The component auto-fixes scroll position.
loadMoreBottomComplete() => voidCall after bottom data finishes loading.
currentScrollStateBubbleListScrollStateCurrent scroll state: AT_BOTTOM / SCROLLED_UP / HAS_NEW_MESSAGES.
currentUnreadCountnumberCurrent unread message count.

Slots

Slot NameContext TypeDescription
#avatarBubbleListItemContextCustom bubble avatar.
#headerBubbleListItemContextCustom bubble header area.
#contentBubbleListItemContextCustom bubble content area.
#footerBubbleListItemContextCustom bubble footer area.
#loadingBubbleListItemContextCustom bubble loading state.
#backToBottomBubbleListBackButtonContextCustom back-to-bottom button. Context includes unreadCount / scrollState / label / autoScroll / virtualEnabled / scrollToBottom(smooth?).
#topStatusBubbleListBoundaryContextCustom top boundary status area. Context includes status / position / scrollState / unreadCount / autoScroll.
#bottomStatusBubbleListBoundaryContextCustom bottom boundary status area, same as #topStatus.
#itemBubbleListItemContextCustom rendering for non-bubble type nodes, triggered when matched by itemType.

title: BubbleList

📌 Warning

Added in version 1.1.6 Added scroll to bottom button, similar to Doubao🔥. Added scrollbar on mouse hover to enhance interaction experience. Please update and try it out.

🐵 This warm tip was last updated: 2025-04-13

💡 Tip

Note: The new version's auto-scroll will automatically scroll when the list length changes. However, after scrolling up, you need to manually call the scrollToBottom method to re-enable auto-scroll. Or, when the scrollbar reaches the bottom, auto-scroll will be triggered again.

The logic is the same as before, so you can upgrade without any worries.

Introduction

BubbleList relies on the Bubble component and is used to display a list of chat bubbles. This component supports setting the maximum list height and has an auto-scroll feature. It also provides various scroll control methods that users can easily call. It is powerful and requires no mental burden for developers.

Code Examples

Basic Usage

Customized List

Auto Scroll & Scroll to Specific Position

Back to Top Button

Theme Overrides (themeOverrides)

Override BubbleList theme tokens via ConfigProvider.themeOverrides. See the full token list and template:

Using with x-markdown-vue

Starting from v2.0.0, the component library no longer bundles XMarkdown / XMarkdownAsync. For Markdown rendering, use x-markdown-vue or see the dedicated page: XMarkdown.

Installation

bash
pnpm add x-markdown-vue
pnpm add katex
pnpm add shiki shiki-stream

💡 Tip

If you need code block syntax highlighting, please install shiki and shiki-stream. Otherwise, you may see this error in the console: Streaming highlighter initialization failed: Error: Failed to load shiki-stream module

Basic Usage

Fog Effect

Enable the typewriter fog animation via the enable-animate prop to simulate AI streaming output.

Props

NameType
Required
DefaultDescription
listArrayYesNoneArray containing bubble information. Each element is an object with content, placement, loading, shape, variant, and other Bubble properties to configure the display and style of each bubble. For Markdown, render via the #content slot.
autoScrollBooleanNotrueWhether to enable automatic scrolling.
maxHeightStringNo'-'Maximum height of the bubble list container.(By default, the height of the wrapper container is inherited)
alwaysShowScrollbarBooleanNofalseWhether to always show the scrollbar. Default is false.
backButtonThresholdNumberNo80Back to bottom button display threshold. When the scrollbar is more than this distance from the bottom, the button will be shown.
showBackButtonBooleanNotrueWhether to show the back to bottom button. Default is true.
backButtonPosition{ bottom: '20px', left: 'calc(50% - 19px)' }No{ bottom: '20px', left: 'calc(50% - 19px)' }Position of the back to bottom button. Default is centered at the bottom.
btnLoadingBooleanNotrueWhether to enable loading state for the back to bottom button. Default is true.
btnColorStringNo'#409EFF'Color of the back to bottom button. Default is '#409EFF'.
btnIconSizeNumberNo24Icon size of the back to bottom button. Default is 24px.

Events

Ref Instance Methods

NameTypeDescription
scrollToTopFunctionScroll to the top.
scrollToBottomFunctionScroll to the bottom.
scrollToBubbleFunctionScroll to the specified bubble index.

Slots

Slot NameParameterTypeDescription
#avatar-SlotCustom avatar display content
#header-SlotCustom bubble header content
#content-SlotCustom bubble content
#loading-SlotCustom bubble loading state content
#footer-SlotCustom bubble footer content

Features

  1. Smart Scrolling - Automatically tracks the latest message position
  2. Deep Customization - Full slot passthrough for bubble components
  3. Multiple Scrolling Methods - Scroll to top, bottom, or specific position
  4. Multiple Styles - Supports various styles such as round, square, etc.