Skip to documentation content

Filter Table

Filter a table's rows with a row of chips that each show how many rows they match.

filter-table-demo

Overview

Filter Table puts a row of chips above a table. Each chip is one filter and shows how many rows it matches. Pressing a chip shows only those rows.

The counts are computed from the rows you pass, so a chip never disagrees with the table under it.

Use Data Table when people also need search, sorting, selection, or pagination.

Anatomy

FilterTable
  • ChipsAll, then one chip for each filter, with its count
  • TableThe matching rows
  • Empty rowA message when the chosen filter matches nothing

Installing filter-table brings Table along as a registry dependency.

Behavior

Filters

One filter is active at a time. All shows every row. A filter is a function, matches, so it can test anything on the row.

Empty

A chip that matches no rows shows 0 and can still be pressed. The table then shows emptyMessage in place of the rows.

Accessibility

The chips are a named group of toggle buttons, and the active one reports that it is pressed. The table uses native table markup with column headers, and is named by label.

When the filter changes, a polite status announces how many rows are shown, as "2 of 5".

KeyAction
TabMove across the chips
Enter or SpaceApply the focused filter

Installation

npx honestui@latest add https://ai.honestui.com/r/filter-table.json

Usage

import { FilterTable } from "@/components/ai/filter-table"

<FilterTable
  label="Agent tasks"
  rows={tasks}
  getRowId={(task) => task.id}
  columns={[
    { id: "title", header: "Task", cell: (task) => task.title },
    { id: "owner", header: "Owner", cell: (task) => task.owner },
  ]}
  filters={[
    { id: "open", label: "Open", matches: (task) => !task.isDone },
    { id: "done", label: "Completed", matches: (task) => task.isDone },
  ]}
/>

Examples

Controlled filter

The active filter is held in state and starts on Failed.

filter-table-controlled

API reference

FilterTable

PropTypeDefaultDescription
labelstringRequiredNames the table.
columnsFilterTableColumn<Row>[]RequiredEach has id, header, and cell.
rowsRow[]RequiredThe rows to show and count.
getRowId(row: Row) => stringRequiredA stable id for each row.
filtersFilterTableFilter<Row>[]RequiredEach has id, label, and matches.
allLabelstring"All"The chip that shows every row.
filtersLabelstringEnglishThe group name read before the chips.
emptyMessagestringEnglishShown when the filter matches no rows.
activeFilterstring | nullNoneThe active filter's id, when you control it.
defaultActiveFilterstring | nullnullThe initially active filter.
onActiveFilterChange(filterId: string | null) => voidNoneRuns when a chip is pressed.