FilterChips
A single-select filter row of chips with leading dots and counts, usable with toolbar or tablist semantics.
FilterChips
Basic Usage
FilterChips
Status filter
Counts are derived from real data rather than typed in as literals.
Loading demo...
Composing With A Table
The chip row only reports which option is selected; the host does the filtering — which keeps the counts, the row data, and the table on one source of truth.
Filter chips with a data table
Counts derive from the row data, and the date column sorts by timestamp rather than by the rendered month text.
Loading demo...
API
Props
| Prop | Type | Default | Description |
|---|---|---|---|
modelValue | string | number | - | Currently selected chip |
items | FilterChipItem[] | [] | The chips |
disabled | boolean | false | Disables the whole row |
role | 'toolbar' | 'tablist' | 'toolbar' | ARIA shape; see Interaction Contract |
indicator | boolean | true | Paints the active fill as one element that slides between chips; off returns it to each chip |
iconOnly | boolean | false | Draws only iconClass, moving label to aria-label and title; a chip without an icon keeps its text |
ariaLabel | string | 'Filters' | Accessible name for the chip row |
FilterChipItem
| Field | Type | Description |
|---|---|---|
value | string | number | Chip identity |
label | string | Chip text |
iconClass | string | Leading icon class, drawn before the dot and the label; omit to render none |
dot | string | Leading dot colour; omit to render no dot |
count | number | Trailing count badge; omit to render none. Derive it from your data |
disabled | boolean | Disables this chip alone |
Events
| Event | Payload | Description |
|---|---|---|
update:modelValue | (value) | Selection changed |
change | (value) | Selection changed, emitted alongside the above |
Slots
| Name | Description |
|---|---|
chip | Replaces a chip's inner content; receives { item, active }. The button shell and keyboard behaviour stay with the component |
Interaction Contract
- The row is a single tab stop: focus lands on the selected chip (or the first enabled one when nothing is selected), and arrow keys move between chips from there.
- Arrow navigation wraps and skips disabled chips;
HomeandEndjump to the ends. - With
role="toolbar"(the default) chips arearia-pressedtoggles and moving focus does not change the filter — activation is explicit. - With
role="tablist"chips becomerole="tab"witharia-selectedand selection follows focus; the host should render the matchingrole="tabpanel"region. - Clicking the already-selected chip emits nothing.
indicator(on by default) paints the active fill as one element and moves it to the new chip. The resting look is pixel for pixel what it is with the indicator off; only the travel between two chips differs. Off, the fill returns to each chip.- The slider is an absolutely positioned child of the scrolling row, so it scrolls sideways with the chips — it measures a chip's
offsetLeft/offsetTop, not viewport coordinates. - A position nobody asked to see travelled to is not tweened: the first paint, a rebuilt chip list (a host refetching its options), and any resize — a webfont landing widens the chips — all land rather than slide.
- With nothing selected the slider is not drawn, rather than parked on chip zero.
- Under
iconOnlyeach chip squares up to a 30px slot (the pill's padding was sized for a word, and a lone glyph would float in the oval) and itslabelmoves toaria-labelandtitle, so assistive tech and hover still get the name. A chip without aniconClassis left alone and keeps its text — a blank chip is worse than a wordy one. - Under
prefers-reduced-motion: reducethe slider lands without a tween. - The no-travel guard lifts only on the frame after the new box has been written to the DOM. Lifting it in the same frame re-arms the transition mid-write and the width tweens up from 0, painting a 0-wide fill on first paint — an ordering bug that shipped once, now pinned by
filter-chips.test.ts. - Counts come from the host: the component cannot see your data and never infers them.
Best Practices
- Always compute counts from the row data. A hardcoded literal starts lying the moment a row is added.
- Keep the filtering in the host: the chips only say which option is selected, and filtered-out rows should genuinely leave the data rather than being hidden with CSS — a hidden row is still in the accessibility tree and the tab order.
- Keep the default
role="toolbar"for plain list filtering; reach fortablistonly when mutually exclusive panels actually exist. - Treat the dot as supplementary. Colour must never be the only carrier of state, so the
labelhas to stand on its own. - Give every chip an
iconClassonce there are more than two or three: a row of bare words runs together into one sentence, and the icon is what gives each chip a leading edge. The icon is decorative (aria-hidden); naming stays withlabel. - Reach for
iconOnlyonly when the glyphs are recognisable on their own (a star, a brand mark). Keep the words when the icons are abstract category symbols — a chip you can only name on hover is not one you can recognise. - Turn
indicatoroff only when the host itself moves the chips during its own animation: two travels layered on each other fight. Not wanting motion is not a reason — the system's reduced motion setting already cuts the tween.
Source
- Component source:
packages/tuffex/packages/components/src/filter-chips/src/TxFilterChips.vue. - Types:
packages/tuffex/packages/components/src/filter-chips/src/types.tsexportsFilterChipsProps,FilterChipItem,FilterChipsRole,FilterChipValue, andFilterChipsEmits. - Test coverage:
packages/tuffex/packages/components/src/filter-chips/__tests__/filter-chips.test.tshas 15 cases covering chip / dot / count rendering, both ARIA shapes,v-modelandchangeemission, silence on re-clicking the active chip, roving tabindex including the no-selection fallback, arrow wrapping and disabled skipping, selection-follows-focus in tablist mode, the disabled state, the chip slot, and the active-fill slider;filter-chips-motion.test.tsadds 3 compiled-style contract cases.
查看源码
packages/tuffex/packages/components/src/filter-chips/index.ts