MenuChevron Down
Fieldset - Docs - Artefact

Fieldset

Layout
Presentational

Introduction

Groups related form controls under a native <fieldset>, with an accessible legend, helper text, and error text. Unlike Field, it has no validator of its own — it's a static, server-rendered grouping primitive, so it never hydrates as a client island. It provides its disabled/invalid/required state as context to nested Fields, matching Ark UI's Fieldset — see Context propagation.

Usage

User Profile

Manage your info.

import { Fieldset, Field } from "../components/ui";

export default function MyPage() {
  return (
    <Fieldset
      legend="User Profile"
      helperText="Manage your info."
      required
      errorText="Something went wrong."
    >
      <Field>...</Field>
    </Fieldset>
  );
}

Passing errorText is enough to put the fieldset into its invalid state — you don't need to also pass invalid. Pass invalid={false} explicitly if you want to suppress the error styling while still keeping the text around.

Context propagation to nested Fields

Fieldset exposes its disabled/invalid/required state as context. Every nested Field reads it as a fallback for its own — so a group-level disabled or required doesn't need to be repeated on each field:

<Fieldset legend="Shipping address" disabled required>
  <Field label="Street" />   {/* renders disabled + required */}
  <Field label="Apt #" required={false} />  {/* opts back out of required */}
</Fieldset>

A Field's own prop always wins over the inherited one. For invalid specifically, inheritance only applies when the Field has no validation of its own (no validator, minLength, or explicit invalid prop) — a Field that validates its own value is never silently overridden by the group.

This propagation is one level: only Field (and anything built on top of it, like Textarea) consults Fieldset's context. A bare Switch or Checkbox placed directly inside a Fieldset — with no wrapping Field — won't pick up the group's styling, though native <fieldset disabled> still blocks interaction with it regardless.

Composition

children is always the group of actual form controls — Fieldset wraps it in a spacing container for you. legend / helperText / errorText accept any Child, not just strings, so rich content (an icon, a badge) belongs there rather than in children:

<Fieldset legend={<>Profile <Badge>New</Badge></>}>
  <Field>...</Field>
  <Textarea>...</Textarea>
</Fieldset>

Don't place FieldsetLegend (or FieldsetHelperText / FieldsetErrorText) inside childrenFieldset wraps children in a <div>, and browsers only use a <legend> to compute the fieldset's accessible name when it's a direct child of <fieldset>, not when it's nested inside a wrapper. The exported sub-components (FieldsetLegend, FieldsetHelperText, FieldsetErrorText, FieldsetContent, FieldsetControl, FieldsetRequiredIndicator) exist for reuse in fully hand-built markup, not as an alternate way to compose within Fieldset itself.

CMS Page Builder

This component is available as a fieldset block in the Page Builder (content/pages/*.json):

{
  "type": "fieldset",
  "legend": "User Profile",
  "helperText": "Manage your info.",
  "required": true,
  "children": [
    { "type": "field", "label": "Name" }
  ]
}

Props

PropTypeDescription
childrenanyForm controls to render inside the fieldset.
classstringCustom CSS classes.
idstringUnique identifier. Auto-generated if omitted.
disabledbooleanDisables the fieldset. Native <fieldset disabled> automatically disables every descendant control, and nested Fields pick it up as context too — see Context propagation.
invalidbooleanWhether the fieldset is in an invalid state. Defaults to true whenever errorText is set, so you usually don't need to pass this explicitly.
requiredbooleanMarks the group as required and appends a required indicator to the legend.
legendChildThe legend text for the fieldset. Always rendered as a direct child of <fieldset> — see Composition.
helperTextChildHelper text shown below the legend.
errorTextChildError text shown when the fieldset is invalid.

CMS bindings

legend, helperText, errorText, disabled, invalid, and required are exposed as editable fields in public/admin/config.yml, plus a children list for nesting other blocks — the same convenience props documented above. id/class and the composition sub-components (FieldsetContent, FieldsetControl, FieldsetRequiredIndicator, etc.) are not exposed: they're a JSX-level API for developers hand-authoring pages, not something a JSON-driven CMS block can express.