<!-- Protocore Design System — Fieldset -->
# Fieldset

- **Category:** Inputs (`inputs`)
- **Slug:** `inputs/fieldset`
- **Status:** stable
- **Platforms:** web
- **Import:** `import { Fieldset } from "@protocore/pds";`
- **Docs:** https://pds.protocore.io/components/inputs/fieldset

> Semantic field group — a mono legend over a hairline content region that disables its children.

## When to use it

Use a **Fieldset** to group **related fields under one heading** — a billing address, a set of notification toggles, a permissions block — and to disable or enable them as a unit. It's the multi-field counterpart to **Field**, which wires a single label/hint/error to one control. Because it renders a real `<fieldset>` / `<legend>`, assistive tech announces the group name with each control inside, and `disabled` propagates natively.

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `children` | `ReactNode` | no | — | The grouped fields/controls. |
| `className` | `string` | no | — | — |
| `description` | `ReactNode` | no | — | Supporting copy shown under the legend (muted, sentence-case). |
| `disabled` | `boolean` | no | — | Disable the whole group — cascades to every native form control inside. |
| `legend` | `ReactNode` | no | — | Group heading — rendered as a mono uppercase legend. |
| `style` | `CSSProperties` | no | — | — |

## Examples

### Basics

A `legend` captions the group and an optional `description` sits below it. The children render inside a hairline-bordered content region — group several `Field`s or controls together.

```tsx
import { Fieldset, Field, Input, Switch } from "@protocore/pds";

export default function Demo() {
  return (
    <div style={{ width: 360 }}>
      <Fieldset legend="Webhook endpoint" description="Where settlement events are delivered.">
        <Field label="URL">
          <Input defaultValue="https://api.trasor.io/hooks/settle" aria-label="URL" />
        </Field>
        <Field label="Signing secret">
          <Input defaultValue="whsec_live_9f2a…" aria-label="Signing secret" />
        </Field>
        <Field label="Retry on failure" htmlFor="retry-switch">
          <Switch id="retry-switch" defaultChecked />
        </Field>
      </Fieldset>
    </div>
  );
}
```

### Disabled group

Setting `disabled` on the Fieldset cascades to every native form control inside via the built-in `fieldset[disabled]` behaviour — no need to disable each child.

```tsx
import { useState } from "react";
import { Fieldset, Field, Input, Switch, Text } from "@protocore/pds";

export default function Demo() {
  const [enabled, setEnabled] = useState(false);

  return (
    <div style={{ display: "grid", gap: 12, width: 360 }}>
      <label style={{ display: "flex", alignItems: "center", gap: 8 }}>
        <Switch checked={enabled} onCheckedChange={setEnabled} />
        <Text size="sm">Enable custom SMTP</Text>
      </label>
      <Fieldset
        legend="SMTP relay"
        description="Overrides the default mail transport."
        disabled={!enabled}
      >
        <Field label="Host">
          <Input defaultValue="smtp.roxana.io" aria-label="Host" />
        </Field>
        <Field label="Port">
          <Input defaultValue="587" aria-label="Port" />
        </Field>
      </Fieldset>
    </div>
  );
}
```

## Do & don't

**Do**

- Use a real `legend` — it names the group for screen readers.
- Group fields that are related and toggle together.
- Use `disabled` to gate a whole section (e.g. until a plan is chosen).
- Nest `Field`s inside for per-control labels and error messaging.

**Don't**

- Don't use it to wrap a single control — use Field.
- Don't disable each child by hand; set `disabled` on the Fieldset.
- Don't put a paragraph in the `legend`; use `description` for that.
- Don't convey grouping with the border alone — keep the legend.

## Accessibility

**Notes**

- Renders a native `<fieldset>` with a `<legend>`, so AT associates the legend with every control inside as a group name.
- The native `disabled` attribute cascades to all descendant form controls — the recommended way to disable a section.
- The legend is mono uppercase to match PDS field captions; the description is muted sentence-case supporting copy.

## Related

`field`, `radio-group`, `checkbox`, `switch`

---

© Protocore. All rights reserved. Use of the Protocore Design System requires prior written authorization from Protocore (contact@protocore.io). These machine-readable materials must not be ingested into ML-training datasets or derivative design systems. See https://pds.protocore.io/legal/
