TinyRobot SuggestionPills:紧凑的建议按钮组组件
在 AI 对话界面中,用户常常需要在对话入口处快速选择预设的操作或提问方向。传统的下拉菜单或长列表虽然能容纳大量选项,但交互路径较长,不够直观。Pill 风格的建议按钮则提供了一种更紧凑、更直观的解决方案------将建议项以胶囊按钮的形式排列展示,用户一目了然、一键即达。
SuggestionPills 正是 TinyRobot 为此场景提供的组件,它具备以下核心能力:
- 紧凑排列:多个建议项以胶囊按钮横向排列,节省纵向空间
- 溢出处理:当建议项超出容器宽度时,支持展开(expand)或横向滚动(scroll)两种模式
- 展开/收起 :通过
showAll控制是否展开全部项,并支持 hover 和 always 两种"更多"按钮显示时机 - 自动滚动:支持鼠标悬停或点击时自动滚动到可见区域
- 自定义按钮:每个药丸按钮可自定义文本和图标,还支持与 DropdownMenu 组合使用
- 点击外部 :提供
click-outside事件,方便实现点击组件外部收起等交互
基本用法:带 items 的 SuggestionPills
最简单的用法是直接在 SuggestionPills 内放置多个 SuggestionPillButton,每个按钮对应一个建议项。
vue
<template>
<TrSuggestionPills>
<TrSuggestionPillButton
v-for="item in items"
:key="item.text"
:item="item"
/>
</TrSuggestionPills>
</template>
<script setup lang="ts">
import { TrSuggestionPills, TrSuggestionPillButton } from '@opentiny/tiny-robot'
const items = [
{ text: '资源管理' },
{ text: '云服务器配置' },
{ text: '安全组设置' },
{ text: '弹性公网IP' },
{ text: '账单查询' },
]
</script>
SuggestionPillItem 类型定义了每个按钮的数据结构,text 和 icon 至少需要提供一个:
typescript
type SuggestionPillItem =
| { text: string; icon?: VNode | Component }
| { text?: string; icon: VNode | Component }
showAll 切换:展开收起折叠项
当建议项较多时,SuggestionPills 默认只显示容器宽度范围内的项,超出的部分被折叠。通过 v-model:showAll 可以控制是否展开全部项。
vue
<template>
<TrSuggestionPills v-model:showAll="showAll">
<TrSuggestionPillButton
v-for="item in items"
:key="item.text"
:item="item"
/>
</TrSuggestionPills>
<button @click="showAll = !showAll">
{{ showAll ? '收起' : '展开全部' }}
</button>
</template>
<script setup lang="ts">
import { TrSuggestionPills, TrSuggestionPillButton } from '@opentiny/tiny-robot'
import { ref } from 'vue'
const showAll = ref(false)
const items = [
{ text: '资源管理' },
{ text: '云服务器配置' },
{ text: '安全组设置' },
{ text: '弹性公网IP' },
{ text: '账单查询' },
{ text: '续费管理' },
{ text: '监控告警' },
{ text: '日志审计' },
]
</script>
showAllButtonOn 属性控制"更多"按钮的显示时机:
'hover'(默认):鼠标悬停在组件上时才显示"更多"按钮'always':始终显示"更多"按钮
vue
<TrSuggestionPills
v-model:showAll="showAll"
show-all-button-on="always"
>
<!-- ... -->
</TrSuggestionPills>
overflowMode:展开 vs 滚动
overflowMode 决定了当建议项超出容器宽度时的展示方式,有两个选项:
'expand'(默认):超出的项折叠隐藏,通过showAll展开'scroll':所有项横向排列,通过横向滚动查看
vue
<template>
<div>
<h4>expand 模式(默认)</h4>
<TrSuggestionPills overflow-mode="expand" style="width: 400px">
<TrSuggestionPillButton
v-for="item in items"
:key="item.text"
:item="item"
/>
</TrSuggestionPills>
<h4>scroll 模式</h4>
<TrSuggestionPills overflow-mode="scroll" style="width: 400px">
<TrSuggestionPillButton
v-for="item in items"
:key="item.text"
:item="item"
/>
</TrSuggestionPills>
</div>
</template>
<script setup lang="ts">
import { TrSuggestionPills, TrSuggestionPillButton } from '@opentiny/tiny-robot'
const items = [
{ text: '资源管理' },
{ text: '云服务器配置' },
{ text: '安全组设置' },
{ text: '弹性公网IP' },
{ text: '账单查询' },
{ text: '续费管理' },
{ text: '监控告警' },
]
</script>
自定义药丸按钮:带图标
SuggestionPillButton 支持通过 icon 插槽或 item.icon 属性添加图标。下面演示使用 icon 插槽自定义图标:
vue
<template>
<TrSuggestionPills>
<TrSuggestionPillButton :item="{ text: '智能推荐' }">
<template #icon>
<IconSparkles style="font-size: 16px; color: #1476ff" />
</template>
</TrSuggestionPillButton>
<TrSuggestionPillButton :item="{ text: '资源管理' }" />
<TrSuggestionPillButton :item="{ text: '安全设置' }" />
</TrSuggestionPills>
</template>
<script setup lang="ts">
import { TrSuggestionPills, TrSuggestionPillButton } from '@opentiny/tiny-robot'
import { IconSparkles } from '@opentiny/tiny-robot-svgs'
</script>
也可以通过 item 属性直接传入图标组件,无需使用插槽:
vue
<TrSuggestionPillButton :item="{ text: '智能推荐', icon: IconSparkles }" />
autoScrollOn 行为
autoScrollOn 属性控制药丸按钮在溢出容器时是否自动滚动到可见区域,支持两种触发方式:
'mouseenter':鼠标悬停到按钮上时自动滚动'click':点击按钮时自动滚动
vue
<template>
<TrSuggestionPills
overflow-mode="scroll"
auto-scroll-on="mouseenter"
style="width: 300px"
>
<TrSuggestionPillButton
v-for="item in items"
:key="item.text"
:item="item"
/>
</TrSuggestionPills>
</template>
<script setup lang="ts">
import { TrSuggestionPills, TrSuggestionPillButton } from '@opentiny/tiny-robot'
const items = [
{ text: '资源管理' },
{ text: '云服务器配置' },
{ text: '安全组设置' },
{ text: '弹性公网IP' },
{ text: '账单查询' },
{ text: '续费管理' },
{ text: '监控告警' },
{ text: '日志审计' },
]
</script>
配合 DropdownMenu 实现更多选项
在实际场景中,药丸按钮点击后可能需要展示更多操作选项。这时可以将 TrSuggestionPillButton 作为 TrDropdownMenu 的触发器,实现"按钮点击 → 弹出下拉菜单"的交互。
vue
<template>
<TrSuggestionPills
ref="pillsRef"
v-model:showAll="showAll"
@click-outside="handleClickOutside"
>
<TrDropdownMenu
v-for="(button, index) in buttons"
:key="index"
:items="dropdownMenuItems"
v-model:show="dropdownShowModels[index]"
trigger="click"
@item-click="handleDropdownItemClick"
>
<template #trigger>
<TrSuggestionPillButton :data-index="index">
{{ button.text }}
</TrSuggestionPillButton>
</template>
</TrDropdownMenu>
</TrSuggestionPills>
</template>
<script setup lang="ts">
import { TrSuggestionPills, TrSuggestionPillButton, TrDropdownMenu } from '@opentiny/tiny-robot'
import { ref, watch } from 'vue'
const showAll = ref(false)
const pillsRef = ref()
const buttons = ref([
{ text: '资源管理1' },
{ text: '资源管理2' },
{ text: '资源管理3' },
{ text: '资源管理4' },
{ text: '资源管理5' },
])
const dropdownMenuItems = [
{ id: '1', text: '去续费' },
{ id: '2', text: '去退订' },
{ id: '3', text: '查账单' },
{ id: '4', text: '导账单' },
]
const dropdownShowModels = ref<boolean[]>([])
watch(
() => buttons.value.length,
(len) => {
dropdownShowModels.value = Array.from({ length: len }, () => false)
},
{ immediate: true }
)
const handleClickOutside = () => {
dropdownShowModels.value.forEach((_, index) => {
dropdownShowModels.value[index] = false
})
showAll.value = false
}
const handleDropdownItemClick = (item: any) => {
console.log('DropdownMenu item clicked:', item)
}
</script>
API 参考
SuggestionPillsProps
| 属性 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
showAll |
boolean |
否 | - | 是否展开全部元素,支持 v-model |
showAllButtonOn |
`'hover' | 'always'` | 否 | 'hover' |
overflowMode |
`'expand' | 'scroll'` | 否 | 'expand' |
autoScrollOn |
`'mouseenter' | 'click'` | 否 | - |
SuggestionPillButtonProps
| 属性 | 类型 | 必填 | 说明 |
|---|---|---|---|
item |
SuggestionPillItem |
是 | 药丸项数据 |
Slots
SuggestionPills 插槽:
| 插槽名 | 说明 |
|---|---|
default |
自定义内容插槽 |
SuggestionPillButton 插槽:
| 插槽名 | 说明 |
|---|---|
default |
自定义内容插槽 |
icon |
自定义图标插槽 |
Events
| 事件名 | 参数 | 说明 |
|---|---|---|
click-outside |
event: MouseEvent |
点击组件外部区域时触发 |
Types
typescript
type SuggestionPillItem =
| { text: string; icon?: VNode | Component }
| { text?: string; icon: VNode | Component }
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 ⭐)