Rime

FilterBar

The one filter row above every table: a growing search, dropdown chips at the end, clear, and the list's own action.

FilterBar lays out a list's filters in a fixed order: a FilterSearch that grows to fill the row, then Select chips (and a DateRangeFilter), then a ghost "Clear filters" while anything is applied, then the list's own action after a hairline ("New invoice").

It is presentational. Filter state lives with the screen, which also decides when to pass onClear (only while a filter is applied). No title, no "n of m shown" line and never a row of toggle chips.

Installation

npx shadcn@latest add KezLahd/rime/filter-bar

Also installs: base, button.

Usage

import { FilterBar, FilterSearch, Select } from "@/components/ui";

<FilterBar aria-label="Filter invoices" onClear={filtering ? clear : undefined} actions={<Button size="sm" iconStart={<IconPlus size={14} />}>New invoice</Button>}>
  <FilterSearch grow aria-label="Search invoices" value={query} onChange={setQuery} placeholder="Customer or invoice number" />
  <Select appearance="chip" aria-label="Status" value={status} onChange={setStatus} active={status !== "all"} options={STATUSES} />
</FilterBar>

Examples

Search, dropdowns, clear and action

Type or pick a status to see Clear filters appear.
Invoices
InvoiceActions
INV-1042Jane Cooper29 Sep 2026$1,280PaidView
INV-1041Wade Warren27 Sep 2026$640SentView
INV-1040Esther Howard24 Sep 2026$2,150OverdueView
INV-1039Cameron Williamson22 Sep 2026$395PaidView

API

Generated from the component's TypeScript types and JSDoc (scripts/gen-ui-registry.mjs), so it always matches the source.

FilterBar

FilterBar props
PropTypeDefaultDescription
childrenRequiredReactNodeThe filters, in order: a <FilterSearch grow /> first, then <Select appearance="chip" /> dropdowns. The search fills whatever the dropdowns leave, so the row always spans the table's full width.
aria-labelRequiredstringNames the filter group for screen readers: "Filter seats".
onClear() => voidShown as a ghost "Clear filters" after the dropdowns. Pass it only while a filter is applied.
clearLabelstring"Clear filters"
actionsReactNodeThe list's own action, at the far end after a hairline: "Add team member".
classNamestring

FilterSearch

FilterSearch props
PropTypeDefaultDescription
valueRequiredstring
onChangeRequired(value: string) => void
placeholderstring"Search"
aria-labelRequiredstring
classNamestring
widthnumber | string220Width of the chip. Defaults to 220px. Ignored when grow is set.
growbooleanFill the row: the search takes every pixel the other filters leave (FilterBar's pattern, where dropdowns sit at the end).

FilterChip

FilterChip props
PropTypeDefaultDescription
activebooleanfalseFilter applied. Shown by tint and ink only, never a ring.
iconReactNode
countnumber
childrenRequiredReactNode

Also accepts the native attributes of AriaAttributes, ButtonHTMLAttributes, DOMAttributes, HTMLAttributes.

Theme tokens

Per-component tokens are undeclared by default, so the default shown is the fallback the CSS uses. Set one at :root (or in theme.css) to restyle every instance. Live values are read from this page, so they follow the Rime Studio.

FilterBar per-component tokens
TokenDefaultLive value
--chip-heightvar(--control-h-sm)…
--chip-radiusvar(--r-sm)…
--filter-bar-gap14px…

System tokens it reads

FilterBar system tokens
TokenDefaultLive value
--brand-deeptokens.css…
--chip-active-filltokens.css…
--chip-active-fill-hovertokens.css…
--chip-active-shadowtokens.css…
--control-h-smtokens.css…
--densitytokens.css…
--durtokens.css…
--easetokens.css…
--focus-colortokens.css…
--focus-ringtokens.css…
--font-bodytokens.css…
--ink-bodytokens.css…
--ink-brandtokens.css…
--ink-disabledtokens.css…
--ink-mutedtokens.css…
--line-glasstokens.css…
--r-2xstokens.css…
--r-fulltokens.css…
--r-smtokens.css…
--recess-filltokens.css…
--recess-fill-hovertokens.css…
--rgb-brandtokens.css…
--rgb-contacttokens.css…
--rgb-whitetokens.css…
--shadow-recesstokens.css…
--text-captiontokens.css…
--wash-activetokens.css…

Accessibility

  • The filters sit in role="group" named by the required aria-label ("Filter invoices").
  • Every chip needs its own aria-label: chips show a value, not a label.
  • Announce result counts from the table region (a polite status line), not from the bar.

Do and don't

Do

  • Order: search, dropdowns, date, clear, then the action.
  • Pass onClear only while a filter is applied.
  • Use FilterSearch here, not SearchField, so the row's heights match.

Don't

  • Never a row of toggle chips for a single-choice filter; use a Select chip.
  • Don't put a heading or result count above the bar.

For AI agents

This page as markdown, rendered from the same registry entry. Point an agent at it (or add .md to this page's URL), or at /llms.txt for the index.

Open filter-bar.md

Related: table, select, date-range-filter