SIG—09 Signature system
QueryBuilder
Conditions that read as a sentence: typed operators per field, nested any/all groups, a plain-language reading and an evaluator for local filtering.
Live — this one is real
Illustrative accounts. The table below is filtered live with matchesQuery; the reading comes from describeQuery.
| Region | ||||
|---|---|---|---|---|
| Cedar Studio | pro | 17 | India | 2026-09-22 |
| Bright Labs | pro | 16 | Japan | 2026-02-11 |
| Harbor Health | pro | 10 | Japan | 2026-08-13 |
| Harbor Foods | pro | 14 | Canada | 2026-08-18 |
| Kite Studio | team | 12 | Canada | 2026-08-31 |
| Signal Studio | pro | 11 | Norway | 2026-06-20 |
Usage
import { useState } from "react";
import { QueryBuilder, type QueryGroup } from "mizu-ui";
export function Example() {
const [query, setQuery] = useState<QueryGroup>({
id: "root",
combinator: "and",
rules: [{ id: "a", field: "plan", operator: "is", value: "pro" }],
});
return (
<QueryBuilder
label="Audience"
value={query}
onValueChange={setQuery}
fields={[
{
id: "plan",
label: "Plan",
type: "select",
options: [
{ value: "free", label: "Free" },
{ value: "pro", label: "Pro" },
],
},
{ id: "seats", label: "Seats", type: "number" },
{ id: "joined", label: "Joined", type: "date" },
]}
/>
);
}
This code, running — no configuration beyond the data
Source & setup
Add this component to your project with the shadcn CLI. The command copies its source and styles into your configured UI directory.
npx shadcn@latest add 0xuser64bit/mizu/query-builderFor npm imports, import mizu-ui/styles.css once. Fonts are optional via mizu-ui/fonts.css. Override --mizu-* tokens or use className for local styling. Requires React and Motion.
Inspect signature/QueryBuilder.tsx
Source is included in the npm package under src/signature/QueryBuilder.tsx.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| label / fields | string / QueryField[] | — | Region name; fields have id, label, type (text, number, date, select, boolean), options and unit. |
| value / defaultValue / onValueChange | QueryGroup | — | The query: a combinator and rules or nested groups. |
| maxDepth | number | 3 | Group nesting limit. |
| footer | ReactNode | — | Beside the reading, e.g. a live match count. |
| describeQuery(query, fields) | function | — | The plain-language reading, for saved segments. |
| matchesQuery(query, record, fields, now?) | function | — | Evaluate a record locally; incomplete rules are ignored. |
Accessibility
Each group is a fieldset; the all/any choice is a real radio group. Every condition is a named group of native selects and inputs with specific labels, and an incomplete condition is described in words. Additions and removals are announced, and a new condition receives focus.
Motion
New conditions unfold from the left, removed ones close, and the and/or joins roll over like a counter when a group's logic changes. Reduced motion shows each change immediately.