caliper uidocs

Query builder

Pro

Build a filter from conditions and nested groups, typed by field: text, number, date, options and yes/no. It reads back as a sentence, counts matches live, flags unfinished conditions and saves segments.

Installs components/ui/query-builder.tsxDepends on @radix-ui/react-popover, @radix-ui/react-slot, lucide-reactMotion none in component source
pnpm dlx shadcn@latest add @caliper/query-builder

Filter accounts

Showing accounts where Plan is any of Team or Business, and MRR ≥ 1000, and (Region is any of EMEA, or Seats between 20 and 60).

6 accounts
Conditions
Match
of these
  • Group, level 2
    Match
    of these
    • and

When to use #

Use it for

  • Segments, audiences and saved filters.
  • Admin search over many fields.

Skip it when

  • Two or three filters; use filter chips.

Installation #

terminal
pnpm dlx shadcn@latest add @caliper/query-builder

Adds its 7 files to components/ui/, each with its own stylesheet, and installs their packages. Pro installs with your access token, set up once per project. See Pro access. The first part also adds Caliper UI’s tokens; import them once as in Installation.

Usage #

Import it from your copy of the source. The example behind the preview comes with the source. It is built from emptyQuery, ruleComplete, matchQuery, describeQuery and QueryBuilder.

example.tsx
import { emptyQuery, ruleComplete, matchQuery, describeQuery, QueryBuilder } from "@/components/ui/query-builder"

The worked example comes with Pro

The 58-line example behind the preview opens here with a Pro or Team licence.

Checking your licence…

API reference #

emptyQuery

component

No props of its own; it re-exports a primitive and takes that primitive’s props.

ruleComplete

component
PropTypeDefault
kind *"rule"—
id *string—
field *string—
operator *string—
valueQueryValue—

matchQuery

component
PropTypeDefault
kind *"group"—
id *string—
combinator *"and" | "or"—
children *readonly (QueryGroup | QueryRule)[]—

describeQuery

component
PropTypeDefault
kind *"group"—
id *string—
combinator *"and" | "or"—
children *readonly (QueryGroup | QueryRule)[]—

QueryBuilder

component
PropTypeDefaultDescription
fields *readonly QueryField[]—
value *QueryGroup—
onChange *(query: QueryGroup) => void—
count((query: QueryGroup) => number)—How many records match, for the live preview.
nounstring"records"What the records are, plural, e.g. "customers".
maxDepthnumber3
segmentsreadonly QuerySegment[][]
onSegmentsChange((segments: QuerySegment[]) => void)—
classNamestring—

Accessibility #

It exposes group semantics, with aria-labelledby, aria-label, aria-hidden, aria-pressed and aria-live kept in step with state. Changes that matter are announced through a live region.

Keyboard and focus handling comes from Radix popover: arrow keys move through items, Enter and Space select, and Escape closes and returns focus.

Motion #

It declares no animation in its component source. Any transition comes from its stylesheet, which uses the duration tokens that collapse to instant under prefers-reduced-motion.