TinyRobot SuggestionPills紧凑的建议按钮组组件

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 类型定义了每个按钮的数据结构,texticon 至少需要提供一个:

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>

在实际场景中,药丸按钮点击后可能需要展示更多操作选项。这时可以将 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 ⭐)

相关推荐
如果超人不会飞1 小时前
TinyRobot Container构建优雅的AI对话容器
前端·vue.js
幸运小圣1 小时前
全面解析 Web 核心性能指标:LCP、INP、CLS 是什么、怎么用、怎么看
前端
如果超人不会飞1 小时前
TinyRobot SuggestionPopover智能建议弹出框组件
前端·vue.js
LiuJun2Son1 小时前
Angular 快速入门:从零搭建你的第一个应用
前端·javascript·angular.js
小徐_23332 小时前
Wot UI 2.1.0 发布:ConfigProvider 全局配置能力升级
前端·uni-app
方白羽2 小时前
Vibe Coding 四个核心阶段
android·前端·app
奶油话梅糖2 小时前
浏览器解析 HTML 头部的底层逻辑:从字节流到资源调度
前端·html
YHL2 小时前
🚀从零理解树与二叉树 —— 概念、实现与遍历
前端·javascript·数据结构
小时前端2 小时前
微前端技术选型深度分析:从概念到实践
前端