Prodular UI

Filter builder

Pro

Nested AND/OR conditions over typed fields: text, number, date, select and yes/no, each with its own operators. The value is plain JSON, with helpers to apply it to rows and describe it in a sentence.

npx prodular-ui add filter-builder

Part of Prodular UI Pro. Preview and read the docs freely, install with a license. See pricing

Filter button over a list

FilterBuilderPopover in a toolbar. applyFilter narrows the rows and describeFilter writes the sentence next to the button.

Status is any of Open or Overdue and Amount is at least 5,000 USD

  • INV-2057Ironclad SecurityOverdue$18,647
  • INV-2041Northwind LogisticsOverdue$5,900
  • INV-2038Kestrel HealthOpen$8,420

3 of 7 invoices

Nested groups

An inline builder for a customer segment, with an OR group inside the AND and a live count of matching accounts.

Expansion candidates

Accounts for the Q4 upgrade campaign

63 of 240 accounts

Where
Where
USD
and
days

Plan is any of Team or Enterprise and (Seats is at least 50 or MRR is at least 5,000 USD) and Last active is in the last 14 days

Anatomy

const [filter, setFilter] = useState(createFilter())
<FilterBuilderPopover fields={fields} value={filter} onValueChange={setFilter} />
const rows = applyFilter(invoices, filter, fields)

Guidance

Use it when

  • Lists and reports where people combine conditions across fields, like overdue invoices over $5,000 for one region.
  • Building segments, audiences and automation rules that are saved and run later.
  • FilterBuilderPopover in a table toolbar; the inline FilterBuilder on a page or in a dialog where the filter is the main task.

Avoid

  • One or two fixed filters on a single field. Use the faceted filters in Data table.
  • Free text search. Use Search input and keep the builder for structured conditions.
  • Groups deeper than one level. maxDepth=1 covers almost every real query.

Rules for AI agents

Published in llms-full.txt, the registry and the MCP server, so coding agents follow them when they build with this component.

  • Describe each filterable column once as a FilterField with id, label and type. Give select fields their options, and number fields a unit when it helps.
  • Keep the value in state as FilterGroup JSON and pass value with onValueChange. Store it as is in saved views or the URL.
  • Filter rows on the client with applyFilter(rows, filter, fields). On the server, walk the same JSON into your query; operators map one to one to SQL.
  • Show describeFilter(filter, fields) next to the trigger or in a saved view so people can read the filter without opening it.
  • To let a model build filters, give it the field list and the FilterGroup shape and ask for JSON. Validate field ids and operators before applying.
  • Incomplete conditions are ignored by applyFilter and countConditions, so never block typing with validation.

API

FilterBuilder

PropTypeDefaultDescription
fieldsFilterField[]Filterable fields: { id, label, type, options?, unit?, icon?, accessor? }.
value / onValueChangeFilterGroup / (value) => voidThe filter tree, controlled.
maxDepthnumber1How deep groups can nest. 0 hides Add group.

FilterBuilderPopover

PropTypeDefaultDescription
labelstring"Filter"Trigger text. The trigger shows the count of active conditions.

applyFilter

PropTypeDefaultDescription
(rows, filter, fields, today?)TRow[]Rows that pass. Pass today to make date conditions deterministic.

describeFilter

PropTypeDefaultDescription
(filter, fields)stringThe filter as one sentence.

countConditions

PropTypeDefaultDescription
(filter)numberComplete conditions, nested groups included.

createFilter

PropTypeDefaultDescription
(combinator?)FilterGroupAn empty filter.

Installation

The Prodular UI CLI adds the source to components/ui with everything it depends on. In a project that already uses shadcn/ui, the shadcn CLI installs it from the Prodular registry too. See Installation for the first setup.

npx prodular-ui add filter-builder# or, with the registry in components.jsonnpx shadcn@latest add @prodular/filter-builder