FilterBar
The filters of a list: a search field, a toolbar of controls, the filters in force as removable chips
and a way to clear them all. It is a GET form, so the filters live in the address.
import { FilterBar } from '@zitdevs/ui';Examples
Section titled “Examples”The demo is server HTML with no React on the page, which runs one script,
enhanceFilterBars(document) from @zitdevs/ui/enhance. Change the kind and the form submits; press
Clear all and the controls reset with focus back on the search field. Tab into the toolbar once
and move between its controls with the arrow keys.
<FilterBar id="people-filters" label="Filter people" action="/people" search={{ id: 'q', label: 'Search people', defaultValue: q }} clearHref="/people" hiddenFields={{ sort: 'name:ascending' }} activeFilters={[{ id: 'kind', label: 'Kind: Employee', removeHref: '/people' }]}> <Select id="kind" label="Kind" options={kinds} defaultValue={kind} /></FilterBar>The page reads the query, filters on the server and passes the filters in force back as
activeFilters. Pair it with a DataTable whose sortFields carry
the same filters.
| Prop | Type | Default | Notes |
|---|---|---|---|
id |
string |
required | The form’s id. |
label |
string |
required | Names the search region, such as “Filter people”. |
action |
string |
required | The page the filters apply to. The method is GET. |
search |
{ id, label, name?, placeholder?, defaultValue? } |
required | The search field, outside the toolbar. name is the id by default. |
children |
ReactNode |
— | The filter controls, in a toolbar: Selects, buttons. Each needs a name to submit. |
activeFilters |
ActiveFilter[] |
[] |
{ id, label, removeHref }: the filters in force, each a chip that is a link. |
clearHref |
string |
— | The list with no filter. Renders the clear-all link. |
hiddenFields |
Record<string, string> |
— | What the form carries besides the filters, such as the sort. Kept when clearing. |
linkAs |
LinkComponent |
'a' |
Renders the chips and the clear link, such as Next’s Link. |
labels |
Partial<FilterBarLabels> |
English | { filters, activeFilters, apply, clearAll, remove }. es.filterBar from labels/es. |
ref |
Ref<HTMLFormElement> |
— | The form. |
| anything else | <form> attributes |
— |
Exported types: FilterBarProps, ActiveFilter, FilterBarLabels, and the label sets
filterBarLabels. From @zitdevs/ui/enhance: enhanceFilterBars, FILTER_BAR_EVENT
(zd:filterchange) and FilterBarChangeDetail.
Accessibility
Section titled “Accessibility”- The form is
role="search", named bylabel. The search field sits outside the toolbar, so its caret keys (arrows, Home, End) keep working. - The controls are a
role="toolbar": one tab stop, with Left and Right (wrapping), Home and End moving between them. On a native select those keys stand in for the select’s own; Up and Down still change its value. - Clear all returns focus to the search field, so a keyboard reader is not left on a link that
went away. Every change is announced on the form as
zd:filterchange. - Each chip is a link named “Remove filter: Kind: Employee”, and the chips are a labelled list.
Without JavaScript
Section titled “Without JavaScript”The form submits with its Apply button, Clear all is a plain link to clearHref and each
chip a link to the list without it, so every path works with no script. What the enhancer adds:
- a change in a toolbar control submits the form;
- Clear all resets the controls, submits through
requestSubmit()and focuses the search field (a click with a modifier still opens the link); - the toolbar’s roving focus.
In React the form’s small client part runs the enhancer once it has hydrated. Without React, call
enhanceFilterBars(document) once; it finds every form[data-filter-bar].
Theming
Section titled “Theming”surface-raised and border-default for the chips, primary for the clear link, ink for text,
the field’s roles for the search field and the focus ring. Nothing is hard-coded.