Skip to content
Redpanda UI
Esc
↑↓navigate↵open⌘Jpreview
Made by eblairmckee
Edit on GitHub

Data Table Filter

Faceted filter bar for data tables with submenu-based option selection, text filters, and operator support.

Installation

Requires React and React DOM 19.2 or later. The copied item declares this API floor; its text-filter debounce uses a local Effect Event so callback changes do not reset the user’s pending edit.

bash
npx shadcn@latest add @redpanda/data-table-filter
bash
pnpm dlx shadcn@latest add @redpanda/data-table-filter
bash
yarn dlx shadcn@latest add @redpanda/data-table-filter
bash
bunx shadcn@latest add @redpanda/data-table-filter
bash
nubx shadcn@latest add @redpanda/data-table-filter
bash
aube dlx shadcn@latest add @redpanda/data-table-filter

When to use

Use this decision tree to determine when to use the Data Table Filter component:

Install the TanStack Table peer dependency if you haven’t already:

bash
npm install @tanstack/react-table

Variants

Use the variant prop to style the filter trigger, active filter pills, and clear button with badge styling.

Keyboard and accessibility

Add, clear, operator, value, and remove actions are native buttons that do not submit a surrounding form. Operator and value controls announce the column they edit and describe the current operator or values. Open a control with Enter or Space, navigate its options with the arrow keys, select with Enter, and close with Escape to return focus to the trigger. Option checkmarks are decorative: the command option is the only selection target, and its description identifies values already included in the filter.

Usage

tsx
import { DataTableFilter, type FilterColumnConfig } from '@/components/redpanda-ui/data-table-filter';import { useDataTable, type DataTableColumnDef } from '@/components/redpanda-ui/data-table';import { useDataTableFilter } from '@/hooks/use-data-table-filter';import { createFilterFn } from '@/lib/filter-utils';

1. Define filter columns

Describe which columns are filterable, what type of filter they use, and the available options:

tsx
const filterColumns: FilterColumnConfig[] = [  {    id: 'status',    type: 'option',    displayName: 'Status',    icon: CircleDotIcon,    options: [      { value: 'open', label: 'Open', icon: CircleIcon },      { value: 'closed', label: 'Closed', icon: CircleCheckIcon },    ],  },  {    id: 'assignee',    type: 'option',    displayName: 'Assignee',    icon: UserIcon,    options: [      { value: 'alice', label: 'Alice' },      { value: 'bob', label: 'Bob' },    ],  },  {    id: 'title',    type: 'text',    displayName: 'Title',    placeholder: 'Search titles…',  },];

2. Wire up TanStack Table columns

Each filterable table column needs a custom filterFn created with createFilterFn:

tsx
import { createFilterFn } from '@/lib/filter-utils';
const tableColumns: DataTableColumnDef<Task>[] = [  { accessorKey: 'title', header: 'Title', filterFn: createFilterFn('text') },  { accessorKey: 'status', header: 'Status', filterFn: createFilterFn('option') },  { accessorKey: 'assignee', header: 'Assignee', filterFn: createFilterFn('option') },];

3. Connect the hook and render

tsx
function TaskTable({ data }: { data: Task[] }) {  const table = useDataTable({    data,    columns: tableColumns,  });
  const { filters, actions } = useDataTableFilter<Task>({    columns: filterColumns,    table,  });
  return (    <div>      <DataTableFilter actions={actions} columns={filterColumns} filters={filters} table={table} />      {/* render your <Table /> below */}    </div>  );}

Filter types

Type Operators Description
text contains, does not contain Free-text search against a column value
option is, is not, is any of, is none of Single-select enum column with automatic operator transition
multiOption include, exclude, include any of, include all of Multi-value column (e.g. tags, labels)

Operators auto-transition when the number of selected values changes. For example, selecting a second value in an option filter automatically switches from is to is any of.

Text filters

Text filters provide free-text search with contains / does not contain operators.

Controlled state

Use the value and onValueChange props on useDataTableFilter to manage filter state externally. This is useful for URL persistence, undo/redo, or syncing with external state.

URL persistence with nuqs

Use nuqs to sync filter state with URL search params so filters survive page refreshes and can be shared via links:

tsx
import { parseAsJson, useQueryState } from 'nuqs';import { type FiltersState } from '@/lib/filter-utils';
function TaskTable({ data }: { data: Task[] }) {  const [filters, setFilters] = useQueryState<FiltersState>('filters', parseAsJson<FiltersState>().withDefault([]));
  const { actions } = useDataTableFilter<Task>({    columns: filterColumns,    table,    value: filters,    onValueChange: setFilters,  });
  return <DataTableFilter actions={actions} columns={filterColumns} filters={filters} table={table} />;}

API Reference

FilterColumnConfig

Configuration for each filterable column.

Prop Type Description
id string Column ID matching a TanStack Table column accessorKey
type "text" | "option" | "multiOption" Filter type
displayName string Human-readable label shown in the filter UI
displayNamePlural string? Plural form for display (defaults to displayName)
icon ComponentType? Icon shown next to the filter name
options FilterOption[]? Available options (for option and multiOption types)
placeholder string? Placeholder text (for text type)

useDataTableFilter<TData>

Hook that manages filter state and syncs it to a TanStack Table instance.

Option Type Description
columns FilterColumnConfig[] Filter column definitions
table DataTableInstance<TData>? Feature-bound TanStack Table V9 instance to sync filters to
value FiltersState? Controlled filter state
onValueChange (filters: FiltersState) => void Callback when filters change (controlled mode)
defaultValue FiltersState? Initial filter state (uncontrolled mode)

Returns { filters, actions, columns }.

DataTableFilterActions

Actions returned by the hook for manipulating filter state.

Method Signature Description
addFilter (columnId: string) => void Add an empty filter for a column
removeFilter (columnId: string) => void Remove the filter for a column
removeAllFilters () => void Clear all active filters
setFilterValues (columnId: string, values: string[]) => void Set the selected values for a filter
addFilterValue (columnId: string, value: string) => void Add a value to a filter
removeFilterValue (columnId: string, value: string) => void Remove a value from a filter
setFilterOperator (columnId: string, operator: string) => void Change the operator for a filter

DataTableFilter

The filter bar component.

Prop Type Description
columns FilterColumnConfig[] Filter column definitions
filters FiltersState Current filter state
actions DataTableFilterActions Actions from useDataTableFilter
table DataTableInstance<TData>? Feature-bound TanStack Table V9 instance (enables faceted counts)
className string? Additional CSS classes
tone BadgeTone? Semantic color shared by the trigger, pills, and clear button; default primary
variant DataTableFilterVariant? Emphasis: solid, subtle (default), or outline

DataTableFilterVariant

Controls emphasis for the trigger button, active pills, and clear button. Choose solid, subtle, or outline, paired with a semantic tone.

The default remains the primary subtle treatment. Flat Badge style keys, including primary-inverted, default-outline, and the disabled paint-only variants, are removed. Disabled-looking paint is not an interaction-disabling API.

tsx
<DataTableFilter  actions={actions}  columns={filterColumns}  filters={filters}  table={table}  tone="default"  variant="outline"/>

Additional patterns

URL-synced filters

Inline filter validation

Credits

Recent changes

  • patchv1.2.0Pin shipped dependency floors to the version we develop against. Registry items now declare ranges like `^5.1.9` (the actual installed version) instead of collapsing to `^5.0.0`, so consumers start on the known-tested baseline while caret semantics still allow any compatible release within the same major.#133
  • minorv1.1.0Theme docs refresh, readability pass on semantic foregrounds, and consumer-facing Base UI regression fixes.#121
  • minorv1.0.0Post-Base-UI polish. Public API unchanged.#116
  • majorv1.0.0Migrate every Radix-based primitive to `@base-ui/react@^1.4.0` (Base UI).#114
  • minorv0.3.0Add theme-provider component to the registry with documentation and tests. Includes playground type improvements (export RegistryItem, remove as-const boilerplate) and docs site dark mode border color fix.#109
See full history →

Last updated on

Was this page helpful?