Skip to content

Patterns · Search and discovery

FilterBar

Filter row: search, removable, editable or toggle FilterChips, an "Add filter" menu, "Clear all", a result count and trailing controls.

@rookcom/monarch-react/dataPattern

Removable filters

StatusOpenAssigneeMePriorityHigh

Usage examples

Search, add filter, editable chip, result count

Quick filters (toggle chips with counts)

Purpose

Shows which filters are applied to a list and lets people change them: search, add a filter, edit or remove one, toggle quick filters, or clear everything, with the result count beside it. FilterChip is one filter; FilterMenu is the "Add filter" menu.

Use when

  • A list or table has filters applied and the user needs to see, change and remove them.
  • Quick one-tap filters ("Assigned to me", "Unread") with counts: FilterChip in toggle mode.

Avoid when

  • Switching between mutually exclusive views: use Tabs or SegmentedControl.
  • Tags on a record: use Badge.

Design principles

  • Chips show field and value ("Status: Open") so filters read without context.
  • The app owns filter state and the filter definitions; FilterBar renders it and reports changes. Pickers (selects, date ranges, people) go in a chip’s editor.
  • "Clear all" appears only when the app passes onClearAll.
  • Toggle chips use aria-pressed, never colour alone.
  • URL state is router-agnostic: readFilterParams / writeFilterParams convert to and from search params.

API reference

import { FilterBar, FilterMenu, defaultFilterBarMessages, readFilterParams, writeFilterParams, FilterChip } from '@rookcom/monarch-react/data';
ExportKindRenderingRoot class
FilterBarcomponentclient.mn-filter-chip
FilterMenucomponentclient.mn-filter-chip
defaultFilterBarMessagesutilityclient–
readFilterParamsutilityclient–
writeFilterParamsutilityclient–
FilterChipcomponentclient.mn-filter-chip

FilterBar and FilterChip are exported from @rookcom/monarch-react (unchanged) and @rookcom/monarch-react/data; FilterMenu, readFilterParams and writeFilterParams from @rookcom/monarch-react/data.

FilterChip has three modes: removable/read-only (default), editable (editor opens a popover from the name and value), and toggle (pressed, defaultPressed or onPressedChange make the whole chip a pressed button).

They render plain elements and pass native attributes through; no refs are forwarded.

messages translates "2 filters", "Filters (n)", the sheet title and "Done".

Generated from the TypeScript declarations of packages/react/src/patterns/search/filter-bar.

Properties

FilterBar

Filter row: search, FilterChips, an add control, "Clear all", a result count and trailing controls.

PropTypeDescription
activeCountnumberNumber of applied filters. Shows "2 filters" and is used by the narrow-screen button.
addReactNodeSlot for an "Add filter" control (FilterMenu, or your own).
childrenReactNode
classNamestring
clearAllLabelstringHide "Clear all" when there is nothing to clear.
collapseBelownumberBelow this width (px) of the bar, chips, the add control and "Clear all" move into a bottom sheet opened by a "Filters (n)" button.
endReactNodeControls on the trailing edge: sort, display options, saved views.
idstring
labelstringAccessible name of the group.
landmarkbooleanExpose the bar as a search landmark (`role="search"`) instead of a group.
messagesPartial<FilterBarMessages>
onClearAll(() => void)Called by the "Clear all" button; the button is hidden when omitted.
resultCountReactNodeResult summary, e.g. "24 results". Announced politely when it changes.
scrollablebooleanKeep chips on one line that scrolls sideways; the pressed chip scrolls into view.
searchReactNodeSearch field on the leading edge, e.g. a SearchInput with `debounce`.

FilterMenu

"Add filter" menu listing the filter fields; put it in FilterBar's `add` slot.

PropTypeDescription
onSelect required(value: string) => voidA field was chosen; open its editor (for example a FilterChip with `editor` and `open`).
options requiredreadonly FilterMenuOption[]Filter fields the user can add.
classNamestring
disabledboolean
labelstringTrigger text. Default "Add filter".
size"xs" | "sm" | "md"

FilterChip

One active filter: removable, editable in a popover, or a pressed toggle.

PropTypeDescription
name requiredstringFilter field, e.g. "Status". In toggle mode, the chip's label, e.g. "Unread".
classNamestring
contentLabelstringAccessible name of the popover. Default "<name> filter".
countnumberCount shown after the label, e.g. matching items.
defaultPressedbooleanInitial pressed state (uncontrolled toggle mode).
editorReactNodeEditor shown in a popover when the chip is pressed (pickers for the value). The name and value become the popover trigger.
idstring
onOpenChange((open: boolean) => void)
onPressedChange((pressed: boolean) => void)
onRemove(() => void)Removes the filter. The remove button is labelled "Remove <name> filter".
openbooleanPopover open state (controlled).
pressedbooleanToggle mode: the whole chip is a pressed/unpressed button (`aria-pressed`), for quick filters such as "Assigned to me". Controlled.
removeLabelstringAccessible name of the remove button. Default "Remove <name> filter".
valueReactNodeCurrent value, e.g. "Open". Optional for toggle chips.

Variants

PropValuesDescription
FilterChip mode'read-only''removable (onRemove)''editable (editor)''toggle (pressed)'Toggle chips are data-variant="toggle" with data-pressed; editable chips are data-editable.
count (FilterChip)'number'A count after the label, e.g. matching items.
landmark'true''false'role="search" instead of role="group".
scrollable'true''false'Chips stay on one line that scrolls sideways; the pressed chip scrolls into view.
collapseBelow'number (px)'Below that width of the bar, chips, the add control and "Clear all" move into a bottom Sheet opened by "Filters (n)".

States

StateExposed asBehaviour
Pressedaria-pressed, data-pressedToggle chip is on: accent border and fill.
Editingaria-expandedThe chip’s popover is open (controlled with open/onOpenChange).
Collapseddata-collapsedNarrow bar: filters are in the sheet.
Hover and focus–Chip buttons and "Clear all" have hover backgrounds and a visible focus ring.

Interaction behaviour

  • The remove button calls onRemove; "Clear all" calls onClearAll.
  • Pressing an editable chip opens its editor in a popover; Escape closes it and returns focus to the chip.
  • Pressing a toggle chip flips it and calls onPressedChange.
  • FilterMenu lists the fields; choosing one calls onSelect (open the new chip’s editor with open).
  • resultCount changes are announced politely; debounce search with SearchInput’s debounce.
  • Order: search, active count, chips, add control, "Clear all", then result count and end at the trailing edge.

Keyboard support

KeysAction
TabMoves through search, chip buttons, remove buttons, add and "Clear all".
Enter / SpaceRemoves, toggles, opens a chip editor, or clears all.
EscapeCloses a chip editor, the add menu or the filter sheet.
Arrow keysMove within the FilterMenu.

Accessibility

Role
group, or search with landmark
Accessible name
label, default "Active filters".
  • Each remove button is labelled "Remove <name> filter" (removeLabel overrides it).
  • Toggle chips are buttons with aria-pressed; their count is part of the name.
  • Chip editors are labelled popovers ("Status filter").
  • The result count is a status region; the narrow-screen button states how many filters are active.
  • Icons are decorative.

Responsive behaviour

  • Chips wrap onto new lines by default; the search field shrinks to fit.
  • scrollable keeps one swipeable line; collapseBelow moves filters into a bottom sheet on phones.

Theme support

  • Chip, pressed, count and focus colours use Monarch semantic tokens, so every theme and contrast mode applies.

Do and don't

Do

  • Move focus somewhere sensible after a removal (the list or the next chip).
  • Hide "Clear all" when nothing is applied.
  • Keep filters in the URL with writeFilterParams so views can be shared and reloaded.

Don't

  • Do not use chips for values the user cannot remove without explaining why.
  • Do not use toggle chips for mutually exclusive options; use SegmentedControl or Tabs.
  • DataTable: The table the filters narrow; pass filtered for its empty state.
  • SavedViews: Saves a filter combination as a named view.
  • SearchInput: The debounced search field for the search slot.
  • Toolbar: Place the FilterBar in its filters slot.
  • Filter Chips (stable): FilterChip registry entry, documented here.
  • SegmentedControl: Mutually exclusive choices.

Dependencies

KindDepends on
npm packagesreact
Monarch componentsButton, DropdownMenu, Popover, Sheet

Testing coverage

  • Remove buttons are labelled per filter and call onRemove; "Clear all" calls onClearAll; default group name.
  • Toggle chips expose aria-pressed and counts, controlled and uncontrolled.
  • Editable chip opens a labelled popover and Escape returns focus.
  • Search, active count, result status region, trailing slot and landmark role.
  • collapseBelow moves filters into a sheet with Clear all and Done; focus returns to the trigger.
  • FilterMenu adds a field by keyboard; readFilterParams / writeFilterParams round-trip.
CheckCovered
Axe in jsdomYes
Server renderingYes
Browser suitesNone yet

Tests: packages/react/src/patterns/search/filter-bar