# 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.

- Family: Signature, imported from `mizu-ui` or `mizu-ui/signature`
- Docs: https://mizu.user64bit.world/components/query-builder
- Source: https://github.com/0xuser64bit/mizu/blob/main/packages/mizu/src/signature/QueryBuilder.tsx

## Usage

```tsx
"use client";

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" },
      ]}
    />
  );
}
```

## Copy it with the shadcn CLI

```sh
npx shadcn@latest init 0xuser64bit/mizu/preset # once, where there is no components.json
npx shadcn@latest add 0xuser64bit/mizu/query-builder
```

## Props

- `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` (default `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.
