# Fieldset

Group related form fields under a shared legend.

Shipping address

[Complete TSX file](/examples/fieldset/default.tsx)

```tsx
"use client";

import { Field, FieldLabel } from "@/siteplane/components/field";
import { Fieldset, FieldsetLegend } from "@/siteplane/components/fieldset";
import { Input } from "@/siteplane/components/input";

export default function Example() {
  return (
    <Fieldset className="w-full max-w-sm">
      <FieldsetLegend>Shipping address</FieldsetLegend>
      <Field name="street">
        <FieldLabel>Street address</FieldLabel>
        <Input autoComplete="street-address" placeholder="Karlsplatz 1" />
      </Field>
      <div className="grid grid-cols-2 gap-3">
        <Field name="city">
          <FieldLabel>City</FieldLabel>
          <Input autoComplete="address-level2" placeholder="Vienna" />
        </Field>
        <Field name="postalCode">
          <FieldLabel>Postal code</FieldLabel>
          <Input autoComplete="postal-code" placeholder="1010" />
        </Field>
      </div>
    </Fieldset>
  );
}
```

## Installation

Complete [one-time setup](/docs/installation/) first.

```bash
pnpm dlx shadcn@4.18.0 add @siteplane/fieldset
```

With npm: `npx shadcn@4.18.0 add @siteplane/fieldset`. [Registry JSON](/registry/fieldset.json) lists source files and dependencies.

For this page’s examples, also install:

```bash
pnpm dlx shadcn@4.18.0 add @siteplane/input @siteplane/radio-group
```

## Usage

```tsx
import {
  Fieldset,
  FieldsetDescription,
  FieldsetLegend,
} from "@/siteplane/components/fieldset";

<Fieldset>
  <FieldsetLegend>Profile</FieldsetLegend>
  <FieldsetDescription>
    Your profile is visible to your team.
  </FieldsetDescription>
</Fieldset>;
```

## Composition

```text
Fieldset
├── FieldsetLegend
├── FieldsetDescription (optional)
├── Field
└── Field
```

## Description

Add `FieldsetDescription` for a hint the whole group shares, such as who sees the details. Its text takes the size and colour of a Card description. The Fieldset names it in `aria-describedby`, so a screen reader reads it when focus enters the group, together with any description id you pass yourself. A hint for one field belongs in that Field's `FieldDescription`.

## Disabled group

Disable the group when the fields are unavailable. This is distinct from a group of read-only values.

Disabled billing details

[Complete TSX file](/examples/fieldset/disabled.tsx)

```tsx
"use client";

import { Field, FieldLabel } from "@/siteplane/components/field";
import { Fieldset, FieldsetLegend } from "@/siteplane/components/fieldset";
import { Input } from "@/siteplane/components/input";

export default function Example() {
  return (
    <Fieldset disabled className="w-full max-w-sm">
      <FieldsetLegend>Billing details</FieldsetLegend>
      <Field>
        <FieldLabel>Company name</FieldLabel>
        <Input defaultValue="Acme Inc." />
      </Field>
      <Field>
        <FieldLabel>Billing email</FieldLabel>
        <Input type="email" defaultValue="billing@example.com" />
      </Field>
    </Fieldset>
  );
}
```

## Choice group

Render a Field as the Fieldset to give a radio group a legend. FieldItem labels each option.

Email digest frequency

[Complete TSX file](/examples/fieldset/choice-set.tsx)

```tsx
"use client";

import {
  Field,
  FieldDescription,
  FieldItem,
  FieldLabel,
} from "@/siteplane/components/field";
import { Fieldset, FieldsetLegend } from "@/siteplane/components/fieldset";
import { Radio, RadioGroup } from "@/siteplane/components/radio-group";

export default function Example() {
  return (
    <Field name="digest" render={(props) => <Fieldset {...props} />}>
      <FieldsetLegend>Email digest</FieldsetLegend>
      <RadioGroup defaultValue="weekly">
        <FieldItem>
          <FieldLabel>
            <Radio value="daily" />
            Daily digest
          </FieldLabel>
        </FieldItem>
        <FieldItem>
          <FieldLabel>
            <Radio value="weekly" />
            Weekly summary
          </FieldLabel>
        </FieldItem>
        <FieldItem>
          <FieldLabel>
            <Radio value="off" />
            Off
          </FieldLabel>
        </FieldItem>
      </RadioGroup>
      <FieldDescription>
        A summary of activity in your projects, sent by email.
      </FieldDescription>
    </Field>
  );
}
```

## API reference

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| Fieldset.disabled | boolean | false | Disables the group and every control in it. |
| FieldsetLegend.children | ReactNode | unset | Names the group. The foundation associates the legend with the fieldset. |
| FieldsetDescription.children | ReactNode | unset | Describes the group. The Fieldset adds its id to aria-describedby. |
| Fieldset.render / FieldsetLegend.render / FieldsetDescription.render | ReactElement \| render function | fieldset / div / p | Composed element. |
| className | string | unset | Additional classes. Fieldset lays out its children in a grid with 12 px gaps, packed at the top, so a Fieldset that a row stretches to a taller neighbour keeps its rows together. The legend takes the strong weight, --sp-rw-font-weight-strong (600). |
`Fieldset` and `FieldsetLegend` wrap the Root and Legend parts of [Base UI
Fieldset](https://base-ui.com/react/components/fieldset) and add no props of
their own. Both accept refs and the other foundation props.
`FieldsetDescription` is a Siteplane UI part with native paragraph props, a ref
and `render`; its id is generated unless you set one. `FieldsetPrimitive`
exports the underlying Base UI Fieldset namespace for its parts and types.

[Read the installed source](/source/fieldset).

## Usage notes

Use a legend that explains what the group has in common. Fieldset does not submit, validate or save the form itself; compose it within [Form](/docs/components/form/).
