组件/FilterChips 筛选胶囊

FilterChips 筛选胶囊

带圆点与计数的单选筛选条,可作为工具栏或标签页语义使用。

Verified自 0.3.9

FilterChips 筛选胶囊

基础用法

FilterChips

状态筛选

计数由真实数据推导,不是写死的字面量。

示例加载中...

与表格组合

筛选条只负责「选了哪一项」,过滤本身由宿主完成——这样计数、行数据与表格永远是同一份真相。

筛选 + 数据表格

计数从行数据推导;日期列按时间戳排序,而不是按渲染出来的月份文本。

示例加载中...

API

Props

属性名类型默认值说明
modelValuestring | number-当前选中的 chip
itemsFilterChipItem[][]chip 列表
disabledbooleanfalse禁用整条筛选条
role'toolbar' | 'tablist''toolbar'ARIA 语义,见「交互契约」
indicatorbooleantrue选中底色作为一个滑块在 chip 之间平移;关掉则退回逐 chip 上色
iconOnlybooleanfalse只画 iconClasslabel 转到 aria-labeltitle;没有图标的 chip 仍显示文字
ariaLabelstring'Filters'筛选条的可访问名

FilterChipItem

字段类型说明
valuestring | numberchip 唯一标识
labelstringchip 文案
iconClassstring前置图标 class,画在圆点与文案之前;不传则不渲染
dotstring前置圆点颜色;不传则不渲染圆点
countnumber尾部计数徽标;不传则不渲染。应当从数据推导
disabledboolean单独禁用该 chip

Events

事件名参数说明
update:modelValue(value)选中变化
change(value)选中变化(与上一条同时触发)

Slots

名称说明
chip替换 chip 内部内容;接收 { item, active }。按钮外壳与键盘行为仍由组件保留

交互契约

  • 整条筛选条只有一个 Tab 停靠点:焦点落在选中的 chip 上(没有选中项时落在第一个可用 chip),方向键在 chip 之间移动。
  • 方向键会绕回,并跳过禁用的 chip;Home / End 直达首尾。
  • role="toolbar"(默认)时 chip 是 aria-pressed 开关,移动焦点不会改变筛选,需要显式激活。
  • role="tablist" 时 chip 变成 role="tab" + aria-selected选中跟随焦点;此时宿主应当同时渲染对应的 role="tabpanel" 区域。
  • 点击已选中的 chip 不会重复触发事件。
  • indicator(默认开)把选中底色画成一个元素并让它平移到新 chip;静止观感与关掉时逐像素一致,区别只在两态之间。关掉后底色回到每个 chip 自己身上。
  • 该滑块是滚动行的绝对定位子元素,因此随 chip 一起横向滚动——它测的是 chip 的 offsetLeft / offsetTop,不是视口坐标。
  • 不该被「看见移动」的位置不会做补间:首帧、chip 列表被重建(宿主重新拉取选项)、以及尺寸变化(含 webfont 落地后 chip 变宽)都是直接落位。
  • 没有任何选中项时不画滑块,而不是让它停在第 0 个 chip 上。
  • iconOnly 下每个 chip 收成 30px 方块(pill 的内边距是为文字留的,单个图标放进去会漂在椭圆里),label 转到 aria-labeltitle,辅助技术与 hover 仍能读到名字。没有 iconClass 的 chip 不受影响,照常显示文字——空 chip 比啰嗦的 chip 更糟。
  • prefers-reduced-motion: reduce 下滑块不做补间,直接落位。
  • 「不补间」的守卫要等新盒子写入 DOM 之后的下一帧才解除。在同一帧解除会让 width 从 0 补间上来,首帧画出 0 宽——这个顺序错误发布过一次,现由 filter-chips.test.ts 钉住。
  • 计数由宿主传入,组件看不到数据,也不会自行推导。

最佳实践

  • 计数一律用 computed 从行数据算出来。写死字面量的那一刻它就开始说谎——新增一行就对不上了。
  • 筛选逻辑放宿主:chip 只表达「选了哪一项」,被过滤掉的行应当真正从数据里移除,而不是靠 CSS 藏起来(藏起来的行仍在无障碍树和 Tab 序列里)。
  • 单纯的列表筛选保持默认 role="toolbar";只有确实存在成组的互斥面板时才用 tablist
  • 圆点是辅助信息,不要让颜色成为状态的唯一载体——label 必须自己说清楚。
  • chip 多于两三个时给每个都配 iconClass:只有文字的一排 chip 会连成一句话,图标是每个 chip 的起始边界。图标是装饰性的(aria-hidden),命名仍然由 label 承担。
  • 图标本身就能认出来时(星标、品牌标)再开 iconOnly;图标只是抽象的类别符号时留着文字,hover 才看到名字的 chip 不算能认。
  • 只有当 chip 会在宿主自己的动效期间被整体重排时才关 indicator:两套位移叠在一起会互相打架。单纯不想要动效不必关它——系统的「减弱动态效果」已经会把补间切掉。

Source

  • Component source: packages/tuffex/packages/components/src/filter-chips/src/TxFilterChips.vue
  • Types: packages/tuffex/packages/components/src/filter-chips/src/types.ts 导出 FilterChipsPropsFilterChipItemFilterChipsRoleFilterChipValueFilterChipsEmits
  • 实测覆盖: packages/tuffex/packages/components/src/filter-chips/__tests__/filter-chips.test.ts 共 15 例,覆盖 chip / 圆点 / 计数渲染、toolbar 与 tablist 两套 ARIA、v-model 与 change 发射、重复点击不发事件、roving tabindex 与无选中时的回退、方向键绕回与跳过禁用项、tablist 下选中跟随焦点、禁用态、chip 插槽与选中滑块;filter-chips-motion.test.ts 另有 3 例编译样式契约。
查看源码
packages/tuffex/packages/components/src/filter-chips/index.ts