Photon Design System

Fieldset

Groups related fields under a shared legend so the relationship is announced to assistive tech. Built on Base UI Fieldset, it renders a native <fieldset> and links the legend to it via aria-labelledby.

Import

import { Fieldset } from "@photon-ai/pho-ui/components/fieldset";

Basic

Fieldset.Legend titles the group; place any fields inside Fieldset.Root.

Billing address
<Fieldset.Root>
  <Fieldset.Legend>Billing address</Fieldset.Legend>
  <Input label="Street" />
  <Input label="City" />
</Fieldset.Root>

Disabled

disabled on Fieldset.Root turns off every control in the group at once — it flows through both the native <fieldset disabled> and Base UI Field, so contained Inputs dim and block input together.

Billing address
<Fieldset.Root disabled>
  <Fieldset.Legend>Billing address</Fieldset.Legend>
  <Input label="Street" />
  <Input label="City" />
</Fieldset.Root>

Anatomy

  • Fieldset.Root — the group container; renders <fieldset> and owns the shared disabled state.
  • Fieldset.Legend — the group title, linked to the fieldset via aria-labelledby.

Props

Fieldset.Root

  • disabled — boolean (default false) — disable every contained field at once
  • className — string — class applied to the <fieldset>
  • …native <fieldset> attributes — children, aria-*, … forwarded to the element

Fieldset.Legend

  • className — string — class applied to the legend
  • children — ReactNode — the group title
  • …native attributes — forwarded to the element

Accessibility

  • Grouping — Fieldset.Root renders a native <fieldset> and points its aria-labelledby at the legend, so assistive tech announces the group name when focus enters any field inside it.
  • Legend — Fieldset.Legend renders as an associated label element; keep it a short noun phrase so the announcement stays tight.
  • Disabled — disabled sets the native <fieldset disabled> and propagates through Base UI Field, so every contained control is disabled and removed from the tab order together.

The fieldset has no interactions of its own — keyboard focus moves through the contained fields as normal.

Best practices

  • Group fields that form one logical unit — an address, a date range, a set of preferences. Don’t wrap a lone field in a fieldset.
  • Keep the legend a short noun phrase (“Billing address”), not a sentence.
  • Reach for disabled on the Root to gate a whole section (e.g. until a toggle is on) rather than disabling each field by hand.
  • For a whole multi-section form, nest fieldsets under a Form rather than inventing your own headings.