Filters

Build rich, shareable filter bars for data-heavy interfaces.

Overview

The Filters composite lets teams surface complex filtering logic through a configurable, accessible UI. Define fields once, then let the component handle operator selection, value inputs, grouped layouts, and optional URL synchronisation.

By default, each field can only be added once. Set allowMultiple when you want repeated filters for the same field. When filters are active, the add menu also includes a built-in Clear all action.

Usage

import {
  Filters,
  defineFilters,
  useFiltersState,
  useFiltersChangeHandler,
} from "@tilt-legal/cubitt-components/composites";
const filterDefs = defineFilters([
  {
    key: "status",
    label: "Status",
    type: "select",
    options: [
      { value: "todo", label: "To Do" },
      { value: "done", label: "Done" },
    ],
  },
  {
    key: "assignee",
    label: "Assignee",
    type: "multiselect",
    options: [
      { value: "john", label: "John" },
      { value: "jane", label: "Jane" },
    ],
  },
] as const);

const [filters, setFilters] = useFiltersState<typeof filterDefs>([]);
const handleFiltersChange = useFiltersChangeHandler<typeof filterDefs>(setFilters);

return <Filters filters={filters} fields={filterDefs.fields} onChange={handleFiltersChange} />;

Examples

Custom Trigger

Validation

Try a non-@tilt.legal address, then blur the field to see the custom validation message.

Data Table Integration

Use Filters to power the rows rendered by DataTable.

Size Variants

Programmatic Presets

URL Sync

Set Presets (Server-Side)

When you need to seed filters outside the UI—redirects, emails, or server-rendered pages—use createFiltersSerializer to produce a validated query string that the Filters component can hydrate from.

If your app configures a custom TanStack Router parseSearch / stringifySearch, pass those same functions into createFiltersSerializer so preset URLs match runtime routing behavior.

import { createFiltersSerializer } from "@tilt-legal/cubitt-components";
import {
  DEFAULT_I18N,
  createFilterArrayValidator,
  defineFilters,
} from "@tilt-legal/cubitt-components/composites";

const definition = defineFilters([
  {
    key: "status",
    label: "Status",
    type: "select",
    options: [
      { value: "todo", label: "To Do" },
      { value: "done", label: "Done" },
    ],
  },
] as const);

const validator = createFilterArrayValidator(definition.fields, DEFAULT_I18N);
const serializeFilters = createFiltersSerializer(validator);

const presetUrl = serializeFilters(
  [
    definition.createFilter("status", "is", ["done"], {
      id: "preset-status-done",
    }),
  ],
  "https://app.tilt.dev/tasks",
);
// -> https://app.tilt.dev/tasks?filters=[...]

API Reference

Filters

PropTypeDefaultDescription
filtersFilter[][]Controlled list rendered by the component.
fieldsFilterFieldsConfig-Definition produced by defineFilters.
onChange(filters: Filter[]) => void-Called whenever a filter is added, edited, or removed.
classNamestring-Additional class names applied to the Filters wrapper.
size"sm" | "md" | "lg""md"Chip sizing.
i18nPartial<FilterI18nConfig>DEFAULT_I18NMerge custom strings with the default copy.
showSearchInputbooleantrueDisplay the field search input in the add menu.
triggerReact.ReactNode-Custom trigger element shown instead of the default add button.
allowMultiplebooleanfalseAllow multiple filters with the same field key.
debugboolean | (filters: Filter[]) => voidfalseEnable logging of filter changes or provide a debug hook.

URL State Props

When paramName is provided the Filters component synchronises its value to TanStack Router search params.

PropTypeDefaultDescription
paramNamestringQuerystring key used to persist filter state. Enables URL synchronisation.
paramHistory"push" | "replace""push"Browser history behaviour applied to URL updates.
paramDebouncenumber150Debounce duration (ms) for URL updates (set 0 to disable).
paramClearOnDefaultbooleantrueRemove the URL parameter when filters match the default state.
paramSerializer(filters: Filter[]) => Promise<void> | voidOptional override invoked before writing filter state to the URL.

Filter Definitions

PropertyTypeDescription
keystringUnique identifier for the filterable field.
labelstringDisplay name shown in the UI.
type'text' | 'select' | 'multiselect' | 'number' | 'date' | 'daterange' | 'boolean' | 'custom' | ...Determines default operators and value editors.
iconReact.ReactNodeOptional icon rendered with the field label.
optionsFilterOption[]Required for select-style fields; each option may include value, label, icon, and metadata.
operatorsFilterOperator[]Override the default operator list for the field.
defaultOperatorstringForce a specific operator when the filter is first created.
placeholderstringPlaceholder text for value inputs.
searchablebooleanEnables search within select / multiselect menus.
maxSelectionsnumberLimit multiselect selections.
classNamestringField-level class names applied to the rendered value control.
min / max / stepnumberNumeric input bounds and stepping for number fields.
prefix / suffixReact.ReactNode | stringInline adornments rendered inside text and number inputs.
group / fieldsFilterFieldGroupGroup fields under a named section.
customRenderer(props: CustomRendererProps) => React.ReactNodeProvide a bespoke value entry UI.
customValueRenderer(values, options) => React.ReactNodeCustom rendering for chip values.
value / onValueChangeunknown[] / (values: unknown[]) => voidOpt into controlled values for a specific field.
validation(value: unknown) => boolean | { valid: boolean; message?: string }Additional validation hook for user-entered values. Return an object to provide a custom error message.

Helpers

  • defineFilters – create strongly typed filter definitions.
  • createFilter – build filters manually.
  • useFiltersState – convenience hook for local state.
  • useFiltersChangeHandler – adapter that forwards onChange results to setState.
  • createFilterArrayValidator – validator compatible with Filters URL-state parsing and serializer helpers.
  • createFiltersSerializer – pure helper for generating validated preset URLs. Pass custom router parseSearch / stringifySearch functions if your app overrides TanStack Router's defaults.

On this page