TinyRobot 全组件使用指南:打造你的 AI 聊天界面,一次搞定!
还在为 AI 聊天界面手搓 DOM 发愁?还在纠结消息气泡怎么排版、输入框怎么搞联想?别慌,TinyRobot 来拯救你了!这套面向 Vue 的 AI 聊天组件库,16 个组件覆盖从"你好"到"再见"的全流程,让你的聊天界面从零到一,比泡面还快。
本文将逐一拆解 TinyRobot 的每一个组件------从最常用的 Bubble、Sender,到冷门但好用的 DragOverlay、McpServerPicker------帮你快速上手,少踩坑,多摸鱼。
一、Bubble 气泡组件 ------ 消息的灵魂容器
如果你要做一个聊天界面,Bubble 就是你的第一个组件。它负责渲染每一条消息------不管是文字、图片、Markdown 还是 AI 的推理过程,都由 Bubble 承包。
核心能力
- 消息展示:文本、图片、Markdown 等多种内容类型一站式渲染
- 流式输出 :
content是响应式的,动态赋值就能实现打字机效果 - 消息分组:连续相同角色的消息自动合并,告别"一条一条往下滚"的尴尬
- 自定义渲染器:Box 渲染器控制气泡样式布局,Content 渲染器控制内容展示,想怎么画就怎么画
- 状态管理 :通过
state属性存储 UI 数据,点赞、展开收起全靠它
快速上手
vue
<template>
<tr-bubble content="你好,我是 AI 助手!" placement="start" />
</template>
就这么简单,一个气泡出来了。
头像和位置
vue
<tr-bubble
content="我来回答你的问题"
:avatar="CustomAvatar"
placement="end"
/>
placement 支持 start(靠左)和 end(靠右),avatar 支持自定义 Vue 节点或组件。
气泡形状
通过 shape 属性设置气泡形状,支持三种风格:
corner(默认):经典聊天气泡,带小尖角rounded:圆角矩形,现代感满满none:无圆角,适合极简风格
vue
<tr-bubble content="圆角风格" shape="rounded" />
流式文本 ------ AI 回答的打字机效果
content 是响应式的!你只需要动态更新 content,气泡就会自动跟着变:
vue
<script setup>
import { ref } from 'vue'
const content = ref('')
// 模拟流式输出
setTimeout(() => { content.value = '正在思考...' }, 500)
setTimeout(() => { content.value = '答案是:42' }, 1500)
</script>
<template>
<tr-bubble :content="content" placement="end" />
</template>
Markdown 渲染
需要先安装依赖:
bash
npm install markdown-it dompurify
然后通过 fallbackContentRenderer 设置 Markdown 渲染器:
vue
<template>
<tr-bubble
:content="mdContent"
:fallback-content-renderer="BubbleRenderers.Markdown"
/>
</template>
<script setup>
import { BubbleRenderers } from '@opentiny/tiny-robot'
</script>
渲染器系统 ------ 想怎么画就怎么画
Bubble 的渲染器架构分两层:
- Box 渲染器:渲染气泡外层容器(样式、布局)
- Content 渲染器:渲染气泡内容(文本、图片、Markdown 等)
渲染器通过 find 函数匹配,优先级由 priority 控制,数值越小越优先。内置渲染器包括:
BubbleRenderers.Text:默认文本渲染BubbleRenderers.Markdown:Markdown 渲染BubbleRenderers.Image:图片渲染BubbleRenderers.Loading:加载状态BubbleRenderers.Reasoning:推理内容(AI 思考过程)BubbleRenderers.Tool:工具调用
自定义渲染器也很简单------写个 Vue 组件,用 markRaw 包装,配置匹配规则即可:
vue
<script setup lang="ts">
import type { BubbleContentRendererProps } from '@opentiny/tiny-robot'
defineProps<BubbleContentRendererProps>()
</script>
<template>
<div class="custom-content">{{ message.content }}</div>
</template>
BubbleList ------ 消息列表
BubbleList 是消息列表组件,负责批量渲染消息并管理分组。
vue
<template>
<tr-bubble-list :messages="messages" :role-configs="roleConfigs" :auto-scroll="true" />
</template>
关键 Props:
| 属性 | 说明 |
|---|---|
messages |
消息数组(必填) |
groupStrategy |
分组策略:consecutive(连续合并)或 divider(按分割角色分组) |
roleConfigs |
各角色默认配置(头像、位置、形状等) |
autoScroll |
是否自动滚动到底部 |
样式定制
Bubble 提供了大量 CSS 变量,从背景色到圆角,从字号到阴影,一应俱全:
css
:root {
--tr-bubble-box-bg: #f0f0f0; /* 气泡背景色 */
--tr-bubble-text-font-size: 14px; /* 文字大小 */
--tr-bubble-box-shape-rounded-radius: 12px; /* 圆角 */
}
二、Sender 消息输入框 ------ 用户打字的终极武器
Sender 是 TinyRobot 中最复杂也最强大的组件------一个高度可组合的聊天输入框,支持文本输入、自动联想、@提及、模板填充、语音输入、文件上传,基本上你能想到的输入交互方式它都覆盖了。
输入模式
支持 single(单行)和 multiple(多行)两种模式。单行模式下内容超宽时自动切换为多行:
vue
<tr-sender v-model="text" mode="single" />
状态控制
vue
<tr-sender v-model="text" :loading="isLoading" :disabled="isDisabled" />
加载状态下点击停止按钮会触发 cancel 事件,方便取消 AI 响应。
提交方式
三种快捷键方案,总有一款适合你:
submitType="enter":Enter 提交,Ctrl+Enter/Shift+Enter 换行submitType="ctrlEnter":Ctrl+Enter 提交,Enter 换行submitType="shiftEnter":Shift+Enter 提交,Enter 换行
扩展系统 ------ Sender 的灵魂
v0.4 的 Sender 用 extensions prop 实现可插拔功能扩展,所有扩展都支持响应式数据自动同步。
模板填充(Template)
typescript
import { TrSender } from '@opentiny/tiny-robot'
const extensions = [TrSender.template(templates)]
// 或标准配置
const extensions = [TrSender.Template.configure({ items: templateData })]
模板数据变化时自动更新编辑器内容,光标自动聚焦到第一个可编辑字段。
提及功能(Mention)
typescript
const extensions = [TrSender.mention(mentions, '@')]
// 支持自定义触发字符
const extensions = [TrSender.mention(mentions, '#')]
输入触发字符(默认 @)弹出选择列表,支持键盘导航和搜索过滤。
智能联想(Suggestion)
typescript
// 不过滤,直接显示所有建议
const extensions = [TrSender.suggestion(suggestions)]
// 自定义过滤
const extensions = [TrSender.suggestion(suggestions, { filterFn: customFilter })]
支持三种高亮模式:自动匹配、精确指定、自定义函数。选中建议项时还有灰色补全提示,按 Tab 一键应用。
语音输入
通过独立的 VoiceButton 组件实现:
vue
<template>
<tr-sender>
<template #footer>
<voice-button
:speech-config="{ lang: 'zh-CN', continuous: true }"
@speech-start="onStart"
@speech-final="onFinal"
/>
</template>
</tr-sender>
</template>
支持浏览器内置语音识别和第三方语音服务(阿里云、百度等),还可以自定义录音 UI(比如移动端的"按住说话")。
文件上传
通过 UploadButton 组件实现:
vue
<template>
<tr-sender>
<template #footer>
<upload-button accept="image/*" :multiple="true" @select="onFilesSelected" />
</template>
</tr-sender>
</template>
支持文件类型过滤、大小限制和数量限制。
自定义插槽
Sender 提供了 header、prefix、footer、footer-right、content、actions-inline 等多个插槽,其中 footer 和 footer-right 插槽提供了 editor、hasContent、disabled、loading 等状态数据以及 focus、insert、append、replace 等操作方法,功能按钮随你定制。
字数限制
vue
<tr-sender v-model="text" :max-length="500" :show-word-limit="true" />
超出限制时红色标示,且无法提交。
样式定制
CSS 变量丰富到可以调出任何风格:
css
.my-sender {
--tr-sender-bg-color: #f5f5f5;
--tr-sender-text-color: #333;
--tr-sender-button-size: 40px;
}
三、Container 容器 ------ 聊天窗口的骨架
Container 是聊天窗口的"外框",提供标题栏、内容区域和底部操作栏,支持全屏和窗口两种模式。
vue
<template>
<tr-container v-model:show="visible" v-model:fullscreen="isFullscreen" title="AI 助手">
<template #default>
<!-- 聊天内容 -->
</template>
<template #footer>
<!-- 输入区域 -->
</template>
</tr-container>
</template>
全屏模式下自动加上 fullscreen 类名,可以用 .fullscreen 选择器自定义样式。
| 属性 | 说明 |
|---|---|
v-model:show |
是否显示容器 |
v-model:fullscreen |
是否全屏 |
title |
容器标题(默认 'OpenTiny NEXT') |
插槽有 default(主体内容)、title(自定义标题区域)、operations(标题栏右侧操作区)、footer(底部操作栏)。
四、Prompts 提示集 ------ 引导用户的第一步
Prompts 是展示提示列表的组件,常用于聊天界面的欢迎页面,引导用户点击预设问题开始对话。
vue
<template>
<tr-prompts
:items="promptItems"
@item-click="onItemClick"
/>
</template>
<script setup>
const promptItems = [
{ label: '帮我写代码', description: '根据描述生成代码片段', icon: CodeIcon },
{ label: '翻译文档', description: '支持多语言互译', badge: '热门' },
]
</script>
关键特性:
- 三种尺寸 :
small、medium(默认)、large - 徽章 :
badge属性给提示项右上角加标签 - 纵向展示 :
vertical属性切换为垂直排列 - 自动换行 :
wrap属性让提示项超出宽度时自动折行 - 响应式布局 :配合
wrap+item-style实现自适应 - 禁用状态 :
disabled属性灰掉提示项
五、Welcome 欢迎组件 ------ 聊天界面的第一印象
Welcome 组件展示欢迎信息,包含标题、描述和图标,常用于新对话的起始页面。
vue
<template>
<tr-welcome
title="你好,我是 AI 助手"
description="有任何问题都可以问我"
align="center"
>
<template #footer>
<tr-prompts :items="promptItems" />
</template>
</tr-welcome>
</template>
align 支持 left、center(默认)、right 三种对齐方式。icon 支持自定义 Vue 节点或 JSX。footer 插槽用来放提示列表等内容。
六、Attachments 附件卡片 ------ 文件也能聊
Attachments 组件展示文件列表,支持图片预览、文件下载、状态显示,让聊天界面也能处理文件。
展示形式
auto(默认):自动检测------全是图片就用图片墙,否则用文件卡片picture:强制图片墙card:强制文件卡片
文件状态
success:上传成功,显示文件大小等元信息uploading:上传中,显示加载动画error:上传失败,显示错误信息和"重试"按钮
vue
<template>
<tr-attachments v-model:items="files" variant="auto" />
</template>
自定义操作按钮
typescript
const actions = [
{ type: 'preview', label: '预览' },
{ type: 'download', label: '下载' },
{ type: 'custom', label: '分享', handler: (file) => shareFile(file) }
]
内置 7 种文件类型识别(image、pdf、word、excel、ppt、folder、other),可以通过 fileMatchers 扩展自定义类型,通过 fileIcons 替换默认图标。
七、Feedback 气泡反馈 ------ 让用户"有话可说"
Feedback 组件附加在消息气泡下方,提供操作按钮、动作按钮和数据来源,让 AI 回答不只是"看",还能"交互"。
vue
<template>
<tr-feedback
:operations="[{ name: 'explain', label: '解释更多' }]"
:actions="[{ name: 'like', label: '有帮助', icon: 'like' }]"
:sources="[{ label: '官方文档', link: 'https://...' }]"
/>
</template>
内置支持的 action 图标:copy、refresh、like、dislike。也可以传入自定义图标。
用 operationsLimit、actionsLimit、sourcesLinesLimit 控制默认显示数量,超出的自动折叠。
八、History 历史记录 ------ 对话也能翻历史
History 组件展示对话历史列表,支持分组、重命名、删除、自定义菜单项等操作。
vue
<template>
<tr-history :data="historyData" :selected="selectedId" @item-click="onItemClick" />
</template>
数据支持两种格式:
- 直接数组:
HistoryItem[] - 分组数组:
HistoryGroup[]
typescript
// 分组格式
const historyData = [
{ group: '今天', items: [{ id: '1', title: '帮我写代码' }] },
{ group: '昨天', items: [{ id: '2', title: '翻译文档' }] }
]
支持自定义菜单项(默认提供重命名和删除),支持 item-prefix 和 item-title 两个插槽自定义显示。
九、SuggestionPills 建议按钮组 ------ 横向建议条
SuggestionPills 是一个横向排列的建议按钮组,适合在输入框上方或聊天界面的快捷操作区域使用。
vue
<template>
<tr-suggestion-pills>
<tr-suggestion-pill-button :item="{ text: '写代码', icon: CodeIcon }" />
<tr-suggestion-pill-button :item="{ text: '翻译' }" />
</tr-suggestion-pills>
</template>
关键特性:
overflowMode:多余项的处理方式------expand(展开显示)或scroll(横向滚动)showAllButtonOn:显示"更多"按钮的时机------hover(默认)或always- 每个药丸项必须包含
text或icon至少一个
十、SuggestionPopover 建议弹出框 ------ 弹出式建议列表
SuggestionPopover 是弹出式的建议列表组件,支持分组数据、自定义渲染、加载状态和移动端适配。
vue
<template>
<tr-suggestion-popover
:data="suggestionData"
title="智能建议"
trigger="click"
@item-click="onItemClick"
/>
template>
触发方式支持 click(点击触发)和 manual(手动控制显示状态)。
数据支持普通项和分组项两种格式,分组项加 group 字段即可。提供了 trigger、item、loading、empty、header、body 六个插槽,灵活度极高。
十一、DropdownMenu 下拉菜单 ------ 轻量级菜单
DropdownMenu 是一个轻量级下拉菜单组件,目前主要服务于 SuggestionPills 的"更多"操作。
vue
<template>
<tr-dropdown-menu :items="menuItems" trigger="click">
<template #trigger>
<button>更多操作</button>
</template>
</tr-dropdown-menu>
</template>
支持三种触发方式:click、hover、manual。show 属性在 click/hover 模式下支持双向绑定,manual 模式下仅单向绑定。
十二、DragOverlay 拖拽浮层 ------ 拖文件进来的视觉提示
DragOverlay 提供拖拽上传的视觉反馈,由 v-dropzone 指令和 <tr-drag-overlay> 组件协同工作。
vue
<template>
<div v-dropzone="dropzoneOptions">
<!-- 你的聊天窗口 -->
</div>
<tr-drag-overlay :is-dragging="isDragging" overlay-title="拖拽文件到这里" />
</template>
<script setup>
const isDragging = ref(false)
const dropzoneOptions = {
onDrop: (files) => handleFiles(files),
onError: (rejection) => console.error(rejection),
onDraggingChange: (dragging) => { isDragging.value = dragging },
accept: '.png,.jpg',
maxSize: 10485760, // 10MB
maxFiles: 3
}
</script>
支持自定义浮层内容(通过 overlay 插槽)、全屏模式、禁用状态。文件被拒绝时会触发 onError,告诉你具体原因(文件类型不符、超大小、超数量等)。
十三、Theme 主题 ------ 一键换肤,支持暗黑模式
ThemeProvider 是主题管理组件,通过 CSS 变量实现主题和暗黑/亮色模式切换。
vue
<template>
<tr-theme-provider color-mode="dark" theme="custom-theme">
<!-- 你的聊天界面 -->
</tr-theme-provider>
</template>
颜色模式
light:亮色dark:暗色auto(默认):跟随系统
自定义主题 CSS
css
[data-tr-theme='custom-theme'][data-tr-color-mode='dark'] {
--tr-bubble-box-bg: #2a2a2a;
--tr-sender-bg-color: #1e1e1e;
}
useTheme 组合式函数
typescript
const { toggleColorMode, setColorMode, setTheme } = useTheme()
toggleColorMode() // 切换亮/暗
setColorMode('dark') // 设置暗色模式
setTheme('custom-theme') // 切换自定义主题
支持嵌套主题、主题数据持久化(通过 storage 和 storageKey 属性),刷新页面自动恢复。
十四、SenderCompat ------ v0.3 的老朋友,升级过渡的好帮手
如果你是从 v0.3.x 升级过来的用户,SenderCompat 就是你的过渡桥梁------保留了大部分 v0.3 的 API,底层用 v0.4 实现,改动最小。
typescript
// 只改一行导入
import { TrSenderCompat as TrSender } from '@opentiny/tiny-robot'
需要处理的 5 个破坏性变更:
- 紧凑模式:
class="tr-sender-compact"→size="small" - 装饰内容插槽:
#decorativeContent→#content+disabled - 模板数据设置:新增
setTemplateData()便捷方法 - 插槽名变更:
#actions→#actions-inline,#footer-left→#footer - 移除不必要的
key绑定
最终迁移路径:v0.3 Sender → SenderCompat → v0.4 Sender
十五、McpAddForm 插件添加表单 ------ MCP 插件的入口
McpAddForm 是添加 MCP 插件的表单组件,支持表单添加和代码添加两种方式。
vue
<template>
<tr-mcp-add-form
:add-type="addType"
:form-data="formData"
@confirm="onConfirm"
@cancel="onCancel"
/>
</template>
表单数据结构:
typescript
interface McpAddFormData {
name: string
description: string
type: 'sse' | 'streamableHttp'
url: string
headers: string
thumbnail?: File | null
}
addType 支持 form(表单模式)和 code(代码模式),两种方式自由切换。
十六、McpServerPicker 插件选择器 ------ MCP 插件管理中心
McpServerPicker 是 MCP 插件的全生命周期管理组件,支持已安装插件和市场插件两个标签页。
vue
<template>
<tr-mcp-server-picker
:installed-plugins="installedList"
:market-plugins="marketList"
v-model:visible="pickerVisible"
v-model:active-count="activeCount"
@plugin-add="onPluginAdd"
@plugin-toggle="onPluginToggle"
/>
</template>
核心功能
- 双标签页:已安装插件 + 市场插件
- 搜索和分类筛选:内置搜索框,市场还支持分类筛选
- 插件状态管理:启用/禁用插件和工具
- 添加状态控制 :
idle(未添加)→loading(添加中)→added(已添加) - 两种弹出方式 :
fixed(固定定位)和drawer(抽屉),通过popupConfig配置
typescript
// 添加状态控制示例
const handlePluginAdd = (plugin) => {
targetPlugin.addState = 'loading' // 显示添加中
addPluginToServer(plugin)
.then(() => { targetPlugin.addState = 'added' })
.catch(() => { targetPlugin.addState = 'idle' }) // 失败重置
}
完整组合示例:打造一个全功能聊天界面
最后,让我们把所有组件组合起来,打造一个完整的 AI 聊天界面:
vue
<template>
<tr-theme-provider color-mode="auto">
<tr-container v-model:show="visible" v-model:fullscreen="fullscreen" title="AI 助手">
<template #default>
<!-- 欢迎页面 -->
<tr-welcome v-if="!messages.length" title="你好" description="有问题尽管问">
<template #footer>
<tr-prompts :items="prompts" @item-click="onPromptClick" />
</template>
</tr-welcome>
<!-- 消息列表 -->
<tr-bubble-list
v-else
:messages="messages"
:role-configs="roleConfigs"
:auto-scroll="true"
>
<template #suffix="{ messages }">
<tr-feedback
:actions="[{ name: 'like', icon: 'like' }, { name: 'copy', icon: 'copy' }]"
:sources="sources"
/>
</template>
</tr-bubble-list>
</template>
<template #footer>
<div v-dropzone="dropzoneOptions">
<tr-sender
v-model="inputText"
:loading="isLoading"
:extensions="extensions"
@submit="onSubmit"
@cancel="onCancel"
>
<template #footer>
<upload-button @select="onFilesSelected" />
<voice-button :speech-config="{ lang: 'zh-CN' }" />
</template>
</tr-sender>
</div>
<tr-drag-overlay :is-dragging="isDragging" overlay-title="拖拽文件到聊天" />
</template>
<template #operations>
<tr-suggestion-pills>
<tr-suggestion-pill-button :item="{ text: '代码', icon: CodeIcon }" />
<tr-suggestion-pill-button :item="{ text: '翻译' }" />
</tr-suggestion-pills>
</template>
</tr-container>
</tr-theme-provider>
</template>
总结
TinyRobot 的 16 个组件,从消息展示(Bubble)到用户输入(Sender),从窗口容器(Container)到主题管理(Theme),从文件处理(Attachments、DragOverlay)到 MCP 插件管理(McpServerPicker、McpAddForm),覆盖了 AI 聊天界面的方方面面。
组件速查表:
| 组件 | 定位 |
|---|---|
| Bubble / BubbleList | 消息气泡与列表 |
| Sender | 消息输入框(含扩展系统) |
| SenderCompat | v0.3 升级过渡组件 |
| Container | 聊天窗口容器 |
| Prompts | 提示集(预设问题列表) |
| Welcome | 欢迎信息展示 |
| Attachments | 附件卡片(文件/图片列表) |
| Feedback | 消息反馈(点赞、复制、来源) |
| History | 对话历史记录 |
| SuggestionPills | 横向建议按钮组 |
| SuggestionPopover | 弹出式建议列表 |
| DropdownMenu | 下拉菜单 |
| DragOverlay | 拖拽上传浮层 |
| ThemeProvider / useTheme | 主题与暗黑模式 |
| McpAddForm | MCP 插件添加表单 |
| McpServerPicker | MCP 插件选择器 |
用这套组件库,一个完整的 AI 聊天界面,从开发到上线,可能比你泡一杯咖啡的时间还短(当然,调试除外 😄)。
OpenTiny NEXT 是一套企业智能前端开发解决方案,以生成式 UI 和 WebMCP 两大核心技术为基础,对现有传统的 TinyVue 组件库、TinyEngine 低代码引擎等产品进行智能化升级,构建出面向 Agent 应用的前端 NEXT-SDKs、AI Extension、TinyRobot智能助手、GenUI等新产品,加速企业应用的智能化改造,实现AI理解用户意图自主完成任务。
欢迎加入 OpenTiny 开源社区。添加微信小助手:opentiny-official 一起参与交流前端技术~
OpenTiny 官网:opentiny.design/
TinyRobot 代码仓库:github.com/opentiny/ti... (欢迎star ⭐)
TinyRobot skill源码:github.com/opentiny/ag... (欢迎 Star ⭐)