Redpanda UI
RC
Redpanda UI

Data Table Filter

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

Made by eblairmckee
Loading component...

When to use

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

Installation

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

npm install @tanstack/react-table

Variants

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

Loading component...

Usage

import { DataTableFilter, type FilterColumnConfig, useDataTableFilter } from "@/components/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:

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:

import { createFilterFn } from "@/lib/filter-utils"

const tableColumns: ColumnDef<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

function TaskTable({ data }: { data: Task[] }) {
  const table = useReactTable({
    data,
    columns: tableColumns,
    getCoreRowModel: getCoreRowModel(),
    getFilteredRowModel: getFilteredRowModel(),
    getFacetedRowModel: getFacetedRowModel(),
    getFacetedUniqueValues: getFacetedUniqueValues(),
  })

  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

TypeOperatorsDescription
textcontains, does not containFree-text search against a column value
optionis, is not, is any of, is none ofSingle-select enum column with automatic operator transition
multiOptioninclude, exclude, include any of, include all ofMulti-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.

Loading component...

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.

Loading component...

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:

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.

PropTypeDescription
idstringColumn ID matching a TanStack Table column accessorKey
type"text" | "option" | "multiOption"Filter type
displayNamestringHuman-readable label shown in the filter UI
displayNamePluralstring?Plural form for display (defaults to displayName)
iconComponentType?Icon shown next to the filter name
optionsFilterOption[]?Available options (for option and multiOption types)
placeholderstring?Placeholder text (for text type)

useDataTableFilter<TData>

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

OptionTypeDescription
columnsFilterColumnConfig[]Filter column definitions
tableTable<TData>?TanStack Table instance to sync filters to
valueFiltersState?Controlled filter state
onValueChange(filters: FiltersState) => voidCallback when filters change (controlled mode)
defaultValueFiltersState?Initial filter state (uncontrolled mode)

Returns { filters, actions, columns }.

DataTableFilterActions

Actions returned by the hook for manipulating filter state.

MethodSignatureDescription
addFilter(columnId: string) => voidAdd an empty filter for a column
removeFilter(columnId: string) => voidRemove the filter for a column
removeAllFilters() => voidClear all active filters
setFilterValues(columnId: string, values: string[]) => voidSet the selected values for a filter
addFilterValue(columnId: string, value: string) => voidAdd a value to a filter
removeFilterValue(columnId: string, value: string) => voidRemove a value from a filter
setFilterOperator(columnId: string, operator: string) => voidChange the operator for a filter

DataTableFilter

The filter bar component.

PropTypeDescription
columnsFilterColumnConfig[]Filter column definitions
filtersFiltersStateCurrent filter state
actionsDataTableFilterActionsActions from useDataTableFilter
tableTable<TData>?TanStack Table instance (enables faceted counts)
classNamestring?Additional CSS classes
variantDataTableFilterVariant?Badge variant applied to filter trigger, pills, and clear button

DataTableFilterVariant

Controls the visual style of the filter trigger button, active filter pills, and the clear button using badge variant tokens.

Available values: neutral, neutral-inverted, neutral-outline, simple, simple-inverted, simple-outline, disabled, disabled-outline, outline, primary-inverted, primary-outline, secondary, secondary-inverted, secondary-outline.

Default: neutral-inverted for pills when no variant is specified; trigger and clear button remain unstyled.

<DataTableFilter
  actions={actions}
  columns={filterColumns}
  filters={filters}
  table={table}
  variant="secondary-outline"
/>

Credits

Built by malinskibeniamin. The source code is available on GitHub.

On this page