Skip to content

Pro pre-sale is open. Installation opens January 2027. See Pro

Components

FilterBar

A row of filters above a table, list or chart: a search field, any filter controls you put in it, a button that clears every filter and the number of results. It wraps onto more lines when the row is narrow.

  • npm: 1 direct, 4 total
  • registry: 4 direct, 4 total

Preview

Props

  • label
  • size
  • activeCount
  • clearLabel
  • resultText
  • filters
import { FilterBar, FilterBarSearch } from "@/components/ui/filter-bar"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"

const clearFilters = () => { /* Reset every filter and the search text. */ }

<FilterBar label="Filter orders" activeCount={1} onClear={clearFilters} resultText="24 orders" className="w-full">
  <FilterBarSearch label="Search orders" placeholder="Search orders" />
  <Select defaultValue="paid">
    <SelectTrigger aria-label="Status" className="w-36">
      <SelectValue />
    </SelectTrigger>
    <SelectContent>
      <SelectItem value="all">All statuses</SelectItem>
      <SelectItem value="paid">Paid</SelectItem>
      <SelectItem value="refunded">Refunded</SelectItem>
    </SelectContent>
  </Select>
</FilterBar>

Usage

When to use

  • Narrow a table, list or chart with a search field and a few filters in one row.
  • Show how many results match and let someone clear every filter at once.

When not to use

  • Search the whole app or run commands. Use Command.
  • Fill in a form that is submitted. Use Field.
  • Switch between views of the same content. Use Tabs.

Variants

size

Height of the search field and the clear button. Give every filter control in the bar the same size: sm above a dense table, md by default.

  • sm

  • mddefault

  • lg

import { FilterBar, FilterBarSearch } from "@/components/ui/filter-bar"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"

const clearFilters = () => { /* Reset every filter and the search text. */ }

<FilterBar size="sm" label="Filter orders" activeCount={1} onClear={clearFilters} resultText="24 orders" className="w-full">
  <FilterBarSearch label="Search orders" placeholder="Search orders" />
  <Select defaultValue="paid">
    <SelectTrigger aria-label="Status" size="sm" className="w-36">
      <SelectValue />
    </SelectTrigger>
    <SelectContent>
      <SelectItem value="all">All statuses</SelectItem>
      <SelectItem value="paid">Paid</SelectItem>
      <SelectItem value="refunded">Refunded</SelectItem>
    </SelectContent>
  </Select>
</FilterBar>
<FilterBar label="Filter orders" activeCount={1} onClear={clearFilters} resultText="24 orders" className="w-full">
  <FilterBarSearch label="Search orders" placeholder="Search orders" />
  <Select defaultValue="paid">
    <SelectTrigger aria-label="Status" className="w-36">
      <SelectValue />
    </SelectTrigger>
    <SelectContent>
      <SelectItem value="all">All statuses</SelectItem>
      <SelectItem value="paid">Paid</SelectItem>
      <SelectItem value="refunded">Refunded</SelectItem>
    </SelectContent>
  </Select>
</FilterBar>
<FilterBar size="lg" label="Filter orders" activeCount={1} onClear={clearFilters} resultText="24 orders" className="w-full">
  <FilterBarSearch label="Search orders" placeholder="Search orders" />
  <Select defaultValue="paid">
    <SelectTrigger aria-label="Status" size="lg" className="w-36">
      <SelectValue />
    </SelectTrigger>
    <SelectContent>
      <SelectItem value="all">All statuses</SelectItem>
      <SelectItem value="paid">Paid</SelectItem>
      <SelectItem value="refunded">Refunded</SelectItem>
    </SelectContent>
  </Select>
</FilterBar>

Examples

Orders

import { FilterBar, FilterBarSearch } from "@/components/ui/filter-bar"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"

const clearFilters = () => { /* Reset every filter and the search text. */ }

<FilterBar label="Filter orders" activeCount={1} onClear={clearFilters} resultText="24 orders" className="w-full">
  <FilterBarSearch label="Search orders" placeholder="Search orders" />
  <Select defaultValue="paid">
    <SelectTrigger aria-label="Status" className="w-36">
      <SelectValue />
    </SelectTrigger>
    <SelectContent>
      <SelectItem value="all">All statuses</SelectItem>
      <SelectItem value="paid">Paid</SelectItem>
      <SelectItem value="refunded">Refunded</SelectItem>
    </SelectContent>
  </Select>
</FilterBar>

Small, above a table

Every control takes the bar's size, sm above a dense table.

import { FilterBar, FilterBarSearch } from "@/components/ui/filter-bar"
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"

<FilterBar label="Filter members" size="sm" resultText="8 members" className="w-full">
  <FilterBarSearch label="Search members" placeholder="Name or email" />
  <ToggleGroup type="single" size="sm" variant="outline" defaultValue="all" aria-label="Role" className="min-w-0 max-w-full flex-wrap gap-y-[max(var(--spacing-xs),calc(var(--size-target-min)-var(--size-element-sm)))]">
    <ToggleGroupItem value="all">All</ToggleGroupItem>
    <ToggleGroupItem value="admin">Admins</ToggleGroupItem>
    <ToggleGroupItem value="member">Members</ToggleGroupItem>
  </ToggleGroup>
</FilterBar>

Search only

import { FilterBar, FilterBarSearch } from "@/components/ui/filter-bar"

<FilterBar label="Filter projects" className="w-full">
  <FilterBarSearch label="Search projects" placeholder="Search projects" />
</FilterBar>

Do and don't

Do

  • Put the search field first and the filters people use most right after it.
  • Give every control in the bar the same size.
  • Keep the results on screen while they update: mark the table pending instead of clearing it.

Don't

  • Do not put actions that change data (Delete, Export) in the bar; put them in the table toolbar.
  • Do not show the clear button when nothing is set.
  • Do not hide the search field's name in the placeholder only.

Props

NameTypeValuesDefaultDescription
label requiredstring--On FilterBar: names the search landmark, such as Filter orders. On FilterBarSearch: names the search field, such as Search orders.
sizeenumsm | md | lgmdHeight of the search field and the clear button. Give every filter control in the bar the same size: sm above a dense table, md by default.
activeCountnumber-0How many filters are set. Above zero, and with onClear, the clear button shows.
onClear() => void--Called by the clear button. Reset every filter and the search text.
clearLabelstring-Clear filtersText of the clear button. Vietnamese: Xóa bộ lọc.
resultTextstring--The number of results, such as 24 orders. Announced politely when it changes.

Slots

NameRequiredDescription
filtersnoChildren of FilterBar: FilterBarSearch and the filter controls, in reading order.

Anatomy

PartDescription
rootThe search landmark: one row that wraps.
searchThe search field. It grows to fill the row, up to 320px from sm up.
filtersAny filter controls between the search field and the clear button: Select, Combobox, DatePicker, ToggleGroup.
clearThe ghost button that clears every filter, shown while activeCount is above zero.
resultThe number of results at the end of the row.

Accessibility

Role: search

KeysAction
TabMoves through the search field, each filter control, then the clear button.
EscapeIn the search field, clears the text (the browser's own search field behavior).
  • A search landmark named by label, such as EN `Filter orders`.
  • The search field is named by its label, not by its placeholder, and has a decorative search icon.
  • The result text is a polite status, so a screen reader hears EN `24 orders` after a filter changes.
  • The clear button shows only while a filter is set; its text says what it does (EN `Clear filters`, VI `Xóa bộ lọc`).

Install

npx werewolf-ui add filter-bar

Run npx werewolf-ui init once in your app before adding components. Init sets up tokens, their CSS import and agent rules. Add installs this component and its dependencies while preserving your theme. See Installation for requirements and the alternative registry setup.