Early bird: 30% off Dashral ProSee pricing

Dashral

Filter BarPro

A filter bar for a table: Filter widens into the filter panel at the bar's own width, fields beside their options, a search widens across the bar, and the filters applied sit under it as chips.

Installation

When to use

  • Above a table or a list with a few fields to narrow it by (status, plan, owner): the filters applied stay in sight as chips, one click from changing.
  • When a field has many options: a long list gets its own search, and each option can say how many rows it would leave.

When not to use

  • One or two filters: a Segmented Control or a Select beside the table is quicker.
  • Filters that need typed ranges or dates: a form fits them better.

Usage

Filter Bar with your own data: a whole component you can paste as a page.

example.tsx
"use client"

import { FilterBar } from "@/components/dashral/pro/filter-bar"

import { useState } from "react"

const fields = [
  {
    id: "status",
    label: "Status",
    options: [
      { value: "active", label: "Active" },
      { value: "trial", label: "Trial" },
      { value: "churned", label: "Churned" },
    ],
  },
  {
    id: "plan",
    label: "Plan",
    multiple: false,
    options: [
      { value: "starter", label: "Starter" },
      { value: "team", label: "Team" },
    ],
  },
]

export default function Customers() {
  const [filters, setFilters] = useState<Record<string, string[]>>({ status: ["active"] })
  const [query, setQuery] = useState("")
  return <FilterBar fields={fields} value={filters} onValueChange={setFilters} search={{ value: query, onValueChange: setQuery }} />
}

API reference

FilterBar

A filter bar whose button widens into the filter panel, at the bar's own width: fields beside their options, a gliding highlight, full keyboard. The filters applied show as chips; a chip opens its own field, × or Backspace removes it.

PropTypeDefault
fieldsFilterField[]

Required.

—
valueFilterValue—
defaultValueFilterValue—
onValueChange(value: FilterValue) => void—
labelstring

The button's words; "Filter" by default.

"Filter"
resultsnumber

The rows the filters leave, for the panel's button ("Show 24 results"); without it the button says Done.

—
searchFilterBarSearch

A search across the bar: its button widens into a field at the bar's width, the rows filtering as you type (the table stays in sight). Closed, what was typed stays as a chip. / opens it.

—
endReact.ReactNode

Anything at the bar's end: a view switch, an export button. It steps back with the bar.

—
classNamestring—
classNamesFilterBarClassNames—

type FilterOption

PropTypeDefault
valuestring—
labelstring—
iconReact.ReactNode

A small mark before it: a dot, an avatar, an icon.

—
countnumber

How many rows it would show, beside it.

—

type FilterField

PropTypeDefault
idstring—
labelstring—
iconReact.ReactNode—
optionsFilterOption[]—
multipleboolean

Several options at once (the default), or one.

—
searchableboolean

A search over its options; on by default past 6 options.

—

type FilterValue

The options picked, by field id. A field with none is left out.

= Record<string, string[]>

type FilterBarClassNames

PropTypeDefault
rootstring—
barstring—
chipstring—
panelstring—

type FilterBarSearch

PropTypeDefault
valuestring—
defaultValuestring—
onValueChange(query: string) => void—
placeholderstring

"Search…" by default.

—

Keyboard

KeysAction
←or→Along the bar: Filter, each chip, Clear, Search and your buttons
EnterOn Filter: open the panel; on a chip: open it on that chip's field
BackspaceorDeleteOn a chip: remove that filter
/Open the search, from anywhere on the page (with search)
↑or↓Through the fields, or a field's options
HomeorEndThe first or last field or option
→orEnterFrom a field into its options
←From the options back to the fields
SpaceorEnterTick an option
EscBack to the fields on a narrow bar, or close; the focus returns where it opened

Accessibility

  • The bar is a toolbar named Filters; each chip reads its filter and how to remove it ("Status: Active, Trial. Press Backspace to remove").
  • The panel is a dialog (aria-modal): the fields are a vertical tablist, a field's options a listbox (multi-select where multiple) with the highlighted option as its active descendant.
  • The search's result count is a live region; the bar's own content is hidden from screen readers while the panel or the search is open.

Motion

  • Filter, a chip or the search button widens to the bar's width (0.42 s) while the bar's content steps back, and shrinks back onto where it came from, scrolling it into view first.
  • Options slide up or down as the field changes and the panel reshapes; chips fade in and out while the others slide over, and the bar's height glides.
  • Smooth tweens on [0.4, 0, 0.2, 1], never springs. With reduced motion it only fades.