Filter bar
Heading + count + filter-controls row for list and table views.
FilterBar is the standard heading-and-controls strip above lists and tables. It renders a heading-sm title and a Counter on the left, filter children on the right, and an optional ghost "Clear filters" button that appears when any filter is active.
Pairs naturally with FilterButton (dropdown filters) and FilterToggle (boolean toggle filters) for the control children.
Use it for
- The header of a list, table, or grid view
- Anywhere the user filters down a known total (
totalandfilteredcounts both surface) - Persistent filters that stay visible while the data changes underneath
Import
import { FilterBar, FilterButton, FilterToggle } from '@brikdesigns/bds';Variants
Default
No filter applied — counter stays neutral and the Clear button is hidden.
<FilterBar
title="Engagements"
total={42}
filtered={42}
label="engagements"
>
<FilterButton label="Status" options={[...]} value={status} onChange={setStatus} />
</FilterBar>Filtered
When filtered < total, the counter switches to its brand style (configurable via activeStatus) and, if onClear is provided, a ghost Clear button appears after the controls.
<FilterBar
title="Engagements"
total={42}
filtered={8}
label="engagements"
onClear={() => clearAllFilters()}
>
<FilterButton ... />
</FilterBar>No title
The title is optional. When omitted the counter leads the row.
No filters
children is optional. A collection with nothing to filter on still gets a title + counter; the controls row is omitted entirely.
<FilterBar title="Brand assets" total={12} filtered={12} label="assets" />Nested under a record heading
Pass titleAs="h3" when the bar sits inside a section that already owns the <h2>.
<FilterBar title="Engagements" titleAs="h3" total={42} filtered={42} label="engagements">
<FilterButton ... />
</FilterBar>No clear callback
Omit onClear to suppress the Clear button entirely — useful for table views that don't support bulk-clearing all filters at once.
Pattern: interactive filter bar
Real-world wiring: local state holds filter values, filtered.length feeds the counter, and onClear resets all filters.
import { FilterBar, FilterButton } from '@brikdesigns/bds';
import { useState, useMemo } from 'react';
function EngagementsTable({ rows }) {
const [status, setStatus] = useState<string | undefined>();
const filtered = useMemo(
() => (status ? rows.filter((r) => r.status === status) : rows),
[rows, status],
);
return (
<FilterBar
title="Engagements"
total={rows.length}
filtered={filtered.length}
label="engagements"
onClear={() => setStatus(undefined)}
>
<FilterButton
label="Status"
value={status}
onChange={setStatus}
options={[
{ id: 'active', label: 'Active' },
{ id: 'pending', label: 'Pending' },
]}
/>
</FilterBar>
);
}When not to use
Don't head a record with a FilterBar. A control bar heads a collection — a table, list, or board of like items. A record — one entity's fields — is headed by a DataSection. The two render at the same heading-sm size, so the choice is about what sits below, not how it looks.
FilterBar is still the right component for a collection with no filterable axes: pass title and the counts, omit children, and the controls row is dropped rather than rendered empty. Don't hand-roll a heading row for that case.
Accessibility
- The title renders as an
<h2>by default. PasstitleAs="h3"when the bar sits under an existing<h2>— a collection tab inside a record page — so the document outline stays contiguous. - The container carries an
aria-label(falls back to"{title} filter bar"or"{label} filter bar"). - The counter announces
"Count: {n}"viaaria-label.
API
FilterBar
| Prop | Type | Default |
|---|---|---|
total | number (required) | — |
filtered | number (required) | — |
label | string (required) | — |
children | ReactNode | — |
title | ReactNode | — |
titleAs | 'h2' | 'h3' | 'h2' |
activeStatus | CounterTone | 'brand' |
onClear | () => void | — |
clearLabel | string | 'Clear filters' |
activeFilterCount | number | — |
actions | ReactNode | — |
Plus all standard <div> HTML attributes (excluding title).
Related
- FilterButton — dropdown control children
- FilterToggle — boolean control children
- Counter — the counter primitive used by the bar
- Storybook playground