# FilterGroup

A flat controlled group of filter conditions with matching and row management.

Connect Flood once using [the installation guide](https://flood.md/docs/installation). Then import the components you use; no per-component add command is needed.

## Example

```tsx
"use client";

import { FloodRoot, FilterGroup } from "@flood-md/react";
import "@flood-md/react/styles.css";

export function Example() {
  return (
    <FloodRoot>
      <FilterGroup label="Project conditions"
        properties={[{id:"status",label:"Status",options:[{value:"active",label:"Active"},{value:"paused",label:"Paused"}]}]}
        value={{match:"all",conditions:[]}} onValueChange={(filters) => console.log(filters)} />
    </FloodRoot>
  );
}
```

## Design notes

- Composes FilterCondition, SegmentedControl, Fieldset, Stack, Inline, Button and IconSlot. The group adds no separate material or decorative nested container.
- value and onValueChange are controlled. Stable condition IDs survive row edits and removals; new rows propose an enabled available property and empty values. Empty values remain an incomplete draft.
- All/any is shown only with at least two conditions. Removing rows preserves the selected match value. An empty group offers Add condition; it does not invent an onboarding message.
- Duplicate properties are prevented for new choices by default. allowDuplicateProperties enables them; maxConditions optionally limits additions. Existing accepted rows are never silently deleted when constraints change. Add remains visible and disabled when no additions are available.
- Accepted additions focus the new property control. Accepted removal focuses a surviving neighbour or Add. Refused controlled proposals do not move focus or mutate accepted conditions; delayed acceptance must not steal focus from a different target.
- label names the group, hideLabel defaults to true, labels localizes group controls, and conditionLabels localizes each row. controlSize defaults to sm; disabled blocks all edits.
- The host owns Apply/Cancel, accepted query evaluation, persistence, validation and server semantics. This is a flat finite-choice editor, not a nested query engine.

## API reference

| Prop | Values | Default |
| --- | --- | --- |
| `legendSize · 0.2.10` | `"label" \| "section"` | `—` |
| `hideLabel · 0.2.3` | `boolean` | `—` |
| `hint` | `ReactNode` | `—` |
| `error` | `ReactNode` | `—` |
| `message` | `ReactNode` | `—` |
| `status` | `"error" \| "warning" \| "success" \| "info"` | `—` |
| `label` | `string` | `Required` |
| `properties` | `readonly FilterConditionProperty[]` | `Required` |
| `value` | `FilterGroupValue` | `Required` |
| `onValueChange` | `(value: FilterGroupValue) => void` | `Required` |
| `controlSize` | `"sm" \| "md" \| "lg" \| "xl"` | `—` |
| `allowDuplicateProperties` | `boolean` | `—` |
| `maxConditions` | `number` | `—` |
| `labels` | `Partial<Record<"match" \| "all" \| "any" \| "add" \| "condition", string>>` | `—` |
| `conditionLabels` | `FilterConditionProps["labels"]` | `—` |
| `Native HTML props` | `Omit<FieldsetHTMLAttributes<HTMLFieldSetElement>, "children" \| "legend" \| "onChange">` | `Forwarded` |
