FilterBar
A row of filter pills over a list that wrap as they're applied, with Clear filters and actions, folding into one button on a phone.
import { FilterBar } from "@butteryui/react";Demo
When to use it
Use it for
- Filtering a table by its fields: status, date, customer
- Showing which filters are applied, each removable
Not for
- Named sets of filters people return to: use SavedViews
- One search box: use SearchField
Examples
Applied filters
Several filters applied at once: the pills wrap, each one removable, and Clear filters takes them all away.
Order filters
Filters over a list of orders: pick a status from its pill, clear it, or export what's shown.
5 of 5 orders
#1041 路 Larkspur Caf茅 路 Paid
#1042 路 Northgate Bakery 路 Unpaid
#1043 路 Wren Street Deli 路 Paid
#1044 路 Saltmarsh Kitchen 路 Refunded
#1045 路 Copperleaf Books 路 Unpaid
Orders table
A filter bar over an orders table: a status pill, and a search among its actions.
5 of 5 orders
Variants and states
Filters
Applied pills are solid with a remove button; press one for its editor. Under 640px they fold into one button.
Props
FilterBar
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | "Filters" | Names the filters for screen readers. Defaults to "Filters". |
actions | ReactNode | Actions at the end of the first line, such as Export. | |
onClearAll | (() => void) | Called by "Clear filters", which shows once any filter is applied. | |
clearLabel | string | Names "Clear filters". | |
applied | number | How many filters are applied, for "Clear filters" and the folded button's count. Counted from the
FilterPills among the children (through fragments) when left out; pass it when your pills sit inside
components of your own. | |
children | ReactNode | The filters, FilterPills. |
It also takes ComponentPropsWithRef<"div">.
FilterPill
| Prop | Type | Default | Description |
|---|---|---|---|
labelrequired | string | The field it filters, such as "Status". | |
value | string | What it's set to, such as "Paid". Leave it out while the filter isn't applied. | |
onRemove | (() => void) | Removes the filter. The applied pill shows a remove button that calls it. | |
children | ReactNode | The filter's editor, in a popover the pill opens. | |
open | boolean | Whether its popover is open. Pair with onOpenChange to control it, such as to close it once a value is picked. | |
defaultOpen | boolean | false | Whether its popover starts open when uncontrolled. Defaults to false. |
onOpenChange | ((open: boolean) => void) | Called when its popover opens or closes. | |
removeLabel | string | Names the remove button. Defaults to "Remove" and the field's name. |
It also takes Omit<ComponentPropsWithRef<"div">, "children">.
Accessibility
A group named Filters. Each pill is a button named by its field and value ("Status: Paid", shown as "Status | Paid") that opens its editor in a popover; an applied pill's remove button is named Remove and the field, with a 24px press area. On a phone the pills move behind one Filters button that says how many are applied.
| Keys | What they do |
|---|---|
| Enter or Space | Opens a pill's editor, removes a filter from its remove button, clears them all from Clear filters, or, folded on a phone, opens the pills |
| Escape | Closes the open editor and puts focus back on its pill |
Motion
It appears with a `Presence` preset and leaves faster than it came, in about 60% of the time.
With reduced motion: A pill's editor, and the folded pills on a phone, fade in and out in 100ms without growing.
Layout
It takes its container's width: the pills sit 8px apart and wrap onto more lines as filters are applied, the actions stay at the end of the first line, centered level with the pills while those fit on one line, and under 640px of its own width the pills fold into one "Filters 路 2" button. Each pill is 28px tall (--bt-h-sm) and truncates its "Field | value" with the full text in its title, and its 16px remove button has a 24px press area.