Filter

Faceted narrowing with visible, removable criteria.

v1.0.0·Updated Jul 8, 2026 · 10:45
Live Demo — Fully Interactive
Search, quick filters, Clear all, and All filters — which opens the panel as a drawer
Configuration
State
Selected count
Label
Status2
<QuickFilter label="Status" selected={2} clearable />
Behavior — The Engineering Contract
Props
PropTypeDefaultDescription
optionsstring[]The values a quick filter or section offers
value / onChangestring[][]Selected values; multi-select
clearablebooleantrueShows the ✕ once anything is picked
maxQuickFiltersnumber4Beyond this, filters live in the panel
onApply / onClearAll() => voidPanel footer actions
collapseAtnumber6Section list length before "+N more"
Events & keyboard
TriggerResult
Toggle an optionFilters the result set immediately (optimistic)
Chip ✕ / Clear allRemoves that filter, or all of them
Escape / outside clickCloses the open dropdown or panel
ApplyCommits the panel's staged selection
Live behavior — every demo is real
Optimistic filtering · statusGET
7 of 7 shown
toggle a status to filter
The list narrows the instant you toggle a filter — no spinner, no wait. A debounced request follows and reconciles the real result count. Filtering should feel like it happens in the browser, because it does.
Anatomy
Status2
1ChipA button-style pill. Quiet when empty, subtly filled once a value is set.
2LabelNames the facet, not the value. "Status", not "Live".
3CountA blue badge with the number of selected values. Hidden at zero.
4CaretFlips up while the dropdown is open.
5ClearRemoves just this filter, appearing only when it holds a value.
Do's and Don'ts
✓ Do
Status2

Show the count. A number on the chip tells the user how many values are active without opening it.

✕ Don't
7 quick filters in one row

Don't line up every facet as a chip. Past four, the rest belong behind "All filters".

✓ Do
Clear all

Give one escape hatch. "Clear all" resets everything in a single, obvious click.

✕ Don't
Apply · then a 3s spinner

Don't block on the network. Filter locally at once, then reconcile — never make the user wait to see a change.

In context: Examples
A · Above a table
Search…Status

The bar sits in the table header — search left, quick filters beside it.

B · As a drawer
All filters

"All filters" opens the full panel as a right-hand drawer for deep faceting.

C · Active filters
Status2Owner1

Active facets read at a glance — each chip carries its own count.

Measurements & Tokens
TokenValueRole
--filter-chip-h34px · radius 8Quick-filter trigger height
--filter-panel-w288pxVertical panel width
--filter-count#3E63DDCount badge (blue), white number
--filter-tab#FF7A00Active tab underline (warm)
--filter-dot#3E63DDSection active indicator
--filter-apply#FF7A00Apply button (the one warm action)
--filter-link#5B8CFFSave / Clear / +N more links
--filter-collapse6 rowsList length before "+N more"
Code
<!-- quick-filter trigger -->
<button class="o-filter__chip is-active">
  Status
  <span class="o-filter__count">2</span>
  <svg class="o-filter__caret">…</svg>
  <button class="o-filter__clear" aria-label="Clear">✕</button>
</button>

<!-- filter bar -->
<div class="o-filter__bar">
  <div class="o-filter__search"><input placeholder="Search here"></div>
  <button class="o-filter__chip">Status</button>
  <button class="o-filter__all">All filters <span class="o-filter__count">2</span></button>
  <button class="o-filter__clear-all">Clear all</button>
</div>