给 Bubble 新增一个 Agent Variant
前言
上一篇已经梳理了 Bubble 组件的可改造点。
如果要从简单到难做二次定制,我建议第一个实际改造点就是:
给
Bubble新增一种适合 Agent 产品的variant。
原因很简单。
variant 属于样式和交互展示层的扩展,风险比较低,但效果很直观。它不涉及后端通信,也不涉及复杂的数据协议,却能让组件从"普通聊天气泡"逐渐变成"Agent 工作台消息"。
这篇文章就以新增
variant="agent"为例,梳理它的设计思路和修改位置。
variant 是什么
在组件库里,variant 通常表示同一个组件的不同视觉形态。
比如同一个 Bubble,可以有这些样式:
| variant | 说明 |
|---|---|
filled |
默认填充背景 |
borderless |
无边框、弱背景 |
outlined |
边框样式 |
shadow |
阴影卡片样式 |
agent |
Agent 工作台样式 |
它们本质上还是同一个 Bubble 组件,只是外观和局部交互表现不同。
使用方式大概是:
vue
<Bubble
variant="agent"
content="我是ikun。"
/>
这样业务侧不用关心内部 class 怎么拼,也不用每次都手写一堆样式,只需要传入一个统一的 variant。
为什么需要 Agent Variant
普通聊天产品和 Agent 产品的消息展示方式不太一样。
普通聊天产品更像即时通讯:
txt
用户:帮我看一下这个组件。
AI:好的,我来帮你看。
这种场景下,左右气泡就够用了。
但 Agent 产品更像一个工作台,AI 回复通常更长,也更结构化:
txt
AI
我已经分析了 Bubble 组件,主要结论如下:
1. Bubble 负责单条消息展示
2. BubbleList 负责消息列表
3. typing 逻辑在 hooks 中处理
4. variant 可以作为样式扩展入口
这种消息如果还用很重的聊天气泡包起来,会显得拥挤。
所以 Agent 风格的 Bubble 可以考虑:
- AI 消息更像内容块,而不是普通气泡
- 背景更轻,适配公司的主题背景色
- 宽度更适合长文本
- 边框和阴影更克制
- 和 header、footer、actions 更容易组合
- 适合承载 Markdown、代码块、文件卡片、思考链等复杂内容
因此,新增 agent variant 的意义不是改一个颜色,而是给 Agent 场景提供一套稳定的消息展示风格。
当前 Bubble 已经有 variant 机制
在当前项目里,Bubble 已经支持 variant。
可以看:
ts
// src/bubble/interface.ts
variant?: 'filled' | 'borderless' | 'outlined' | 'shadow';
也就是说,当前已有四种内置样式:
filledborderlessoutlinedshadow
直接上四种效果图
在 Bubble.vue 中,组件会根据 variant 生成 content 的 class:
tsx
class={[
`${prefixCls}-content`,
`${prefixCls}-content-${variant}`,
{ [`${prefixCls}-content-${shape}`]: shape },
contextConfig.value.classNames.content,
classNames.content,
]}
如果 variant="filled",最终就会生成类似这样的 class:
html
class="ant-bubble-content ant-bubble-content-filled"
如果新增 variant="agent",最终就会生成:
html
class="ant-bubble-content ant-bubble-content-agent"
所以这个项目已经把扩展入口留好了。
我们要做的是:
- 扩展类型
- 增加样式
- 增加示例
- 验证效果
第一步:扩展类型定义
首先修改:
txt
src/bubble/interface.ts
当前写法是:
ts
variant?: 'filled' | 'borderless' | 'outlined' | 'shadow';
可以扩展为:

这样使用组件时,TypeScript 就允许传入:
vue
<Bubble variant="agent" />
这一步的作用是让组件 API 正式支持新值。
如果不改类型,样式可能也能通过字符串传进去,但编辑器会报类型错误,组件库对外使用也不规范。
第二步:确认 Bubble.vue 是否需要改
当前 Bubble.vue 里已经根据 variant 自动生成 class:
tsx
`${prefixCls}-content-${variant}`
所以如果只是新增一种样式分支,Bubble.vue 不一定需要改。
这是一个很好的组件设计点。
因为它没有把每个 variant 写死成条件判断:
ts
if (variant === 'filled') {}
if (variant === 'outlined') {}
而是统一拼接 class。
这样新增一个 variant 的成本就很低。
也就是说,agent variant 主要需要改类型和样式,不需要大改渲染逻辑。
第三步:增加样式
Bubble 的 variant 样式在:
txt
src/bubble/style/content.ts
当前 genVariantStyle 大致结构是:

新增 agent 时,可以在这里增加一段:
ts
'&-agent': {
padding: `${unit(token.padding)} ${unit(token.paddingLG)}`,
borderRadius: token.borderRadiusLG,
backgroundColor: token.colorBgContainer,
border: `1px solid ${token.colorBorderSecondary}`,
}
这样 ant-bubble-content-agent 就会有自己的样式。
不过只加这一段还比较普通。
如果想让它更像 Agent 消息,可以稍微设计得更明显一些:
ts
'&-agent': {
padding: `${unit(token.padding)} ${unit(token.paddingLG)}`,
borderRadius: token.borderRadiusLG,
backgroundColor: token.colorBgContainer,
border: `1px solid ${token.colorBorderSecondary}`,
boxShadow: token.boxShadowTertiary,
}
这样 AI 消息会更像一个内容块。
但也要注意,不要一上来样式太重。Agent 消息通常内容较长,如果背景、边框、阴影都很强,会影响阅读。

第四步:考虑 placement 的差异
Bubble 还有一个重要属性:
ts
placement?: 'start' | 'end';
一般来说:
placement="start"表示 AI 消息,靠左placement="end"表示用户消息,靠右
如果 agent variant 主要用于 AI 消息,可以让它更适合 start。
例如:
vue
<Bubble
placement="start"
variant="agent"
content="我正在分析这个组件。"
/>
用户消息仍然可以使用默认的 filled:
vue
<Bubble
placement="end"
variant="filled"
content="帮我看一下 Bubble。"
/>
这样就能形成一种比较自然的 Agent 对话风格:
- 用户消息短,右侧气泡
- AI 消息长,左侧内容块
这一点很适合写进公司定制方案里。
第五步:在 play 中验证
新增 variant 后,应该在 play 里加一个简单示例。
比如在:
txt
play/src/App.vue
写一个对比 demo:
vue
<template>
<div class="demo">
<Bubble
placement="end"
variant="filled"
content="帮我看一下 Bubble 组件可以怎么改。"
/>
<Bubble
placement="start"
variant="agent"
content="我已经分析了 Bubble 组件。它主要可以从样式层、插槽层、状态层和列表层进行改造。"
/>
</div>
</template>
如果要更像真实 Agent 产品,可以加上 header 和 footer:
vue
<Bubble
placement="start"
variant="agent"
content="我已经分析了 Bubble 的源码结构,下面是几个建议修改点。"
>
<template #header>
AI Assistant
</template>
<template #footer>
<button>复制</button>
<button>重新生成</button>
</template>
</Bubble>
这个 demo 不需要接后端,也不需要做真实发送。
它的目的只是验证:
- 新 variant 是否生效
- 布局是否合理
- AI 消息和用户消息是否有明显区分
- header/footer 是否能正常组合
- 长文本阅读体验是否舒服
第六步:考虑 BubbleList 中的角色配置
单个 Bubble 可以直接传 variant。
但真实对话里一般会用 BubbleList。
BubbleList 支持通过 roles 给不同角色配置默认属性。
例如可以这样设计:
ts
const roles = {
assistant: {
placement: 'start',
variant: 'agent',
},
user: {
placement: 'end',
variant: 'filled',
},
};
这样消息数据里只需要写 role:
ts
const items = [
{
key: '1',
role: 'user',
content: '帮我看一下 Bubble。',
},
{
key: '2',
role: 'assistant',
content: '我已经看完了,它主要负责单条消息展示。',
},
];
最终效果是:
- user 自动用
filled - assistant 自动用
agent
这比每条消息都手动写 variant 更适合业务场景。
因此,agent variant 不只是单个组件的样式扩展,也可以成为消息角色系统的一部分。
agent variant 可以怎么设计
我个人更建议 agent variant 做成轻量工作台风格,而不是传统卡片风格。
可以考虑这些特征:
| 设计点 | 建议 |
|---|---|
| 背景 | 使用弱背景或白色背景 |
| 边框 | 使用浅边框,增强内容边界 |
| 圆角 | 中等圆角,不要过于圆润 |
| 阴影 | 可以很弱,或者不加 |
| 宽度 | 比普通气泡更宽 |
| padding | 比普通气泡更大,适合长文本 |
| footer | 适合放复制、重新生成、反馈按钮 |
| content | 适合承载 Markdown 和结构化内容 |
也就是说,它应该更像:
txt
AI Assistant
我已经分析完这个组件,主要有以下几点:
1. ...
2. ...
3. ...
[复制] [重新生成] [反馈]
而不是:
txt
[ 一大段内容挤在一个聊天泡泡里 ]
为什么不直接改 filled
可能会有一个疑问:
既然默认的 filled 不适合 Agent 产品,为什么不直接改 filled?
原因是:
filled是通用样式,agent是业务场景样式。
如果直接改 filled,会影响所有使用默认填充样式的地方。
而新增 agent 的好处是:
- 不破坏原有能力
- 兼容已有示例
- 业务侧可以按需选择
- 后续可以继续扩展
- 更符合组件库设计方式
组件库里比较重要的一点就是不要轻易破坏默认行为。
所以新增 variant 通常比直接覆盖默认样式更稳。
这个改造的工作量怎么描述
需要注意的问题
新增 variant 看起来简单,但有几个点要注意。
第一,不要只改样式,不改类型。
如果只加了 CSS,但 interface.ts 里没有加 agent,业务侧使用时会有类型错误。
第二,不要把业务逻辑塞进 variant。
variant 应该主要控制外观,不应该负责请求接口、判断消息状态、解析工具调用。
第三,不要影响已有 variant。
新增 agent 时,不应该破坏 filled、outlined、shadow 的原有表现。
第四,最好加 demo。
组件库的改动如果没有示例,后面别人很难理解这个 variant 应该怎么用。
推荐修改文件
如果真正落地这个改造,主要涉及这些文件:
txt
src/bubble/interface.ts
src/bubble/style/content.ts
play/src/App.vue
其中:
| 文件 | 作用 |
|---|---|
src/bubble/interface.ts |
扩展 variant 类型 |
src/bubble/style/content.ts |
新增 agent 样式 |
play/src/App.vue |
增加示例和视觉验证 |
当前 Bubble.vue 已经会自动生成 ${prefixCls}-content-${variant},所以不一定需要改。
这是因为组件原本的扩展方式比较合理。
总结
新增 agent variant 是一个很适合作为 Bubble 二次定制第一步的改造点。
它的优点是:
- 难度低
- 风险小
- 效果直观
- 不涉及通信层
- 能体现组件库扩展思路
- 适合公司 Agent UI 定制
它的核心改造路径是:
txt
扩展 variant 类型
-> 增加 agent 样式
-> 在 play 中验证
-> 在 BubbleList roles 中使用
这个改造完成后,Bubble 就不只是普通聊天气泡,而是可以开始承载更像 Agent 工作台的消息展示形态。
下一步可以继续围绕 agent variant 做消息操作区,比如复制、重新生成、点赞、点踩等交互。