moduix

Fieldset

A composable fieldset for grouping related form controls under one accessible legend.

API Reference

Original primitive API

Behavior, accessibility details, and low-level props are documented by Base UI.

Base UI API

Basic

Billing details
import {  Fieldset,  FieldsetLegend,  Field,  FieldLabel,  FieldControl,  FieldError,} from "moduix";export function FieldsetDemo() {  return (    <Fieldset>      <FieldsetLegend>Billing details</FieldsetLegend>      <Field validationMode="onBlur">        <FieldLabel>Company</FieldLabel>        <FieldControl required placeholder="Enter company name" />        <FieldError match="valueMissing">Please enter company name.</FieldError>      </Field>      <Field validationMode="onBlur">        <FieldLabel>Tax ID</FieldLabel>        <FieldControl required placeholder="Enter tax ID" />        <FieldError match="valueMissing">Please enter tax ID.</FieldError>      </Field>    </Fieldset>  );}

Full list of component variables available for project-level overrides.

PropertyDefaultDescription
--fieldset-border-colortransparentControls the root fieldset border color.
--fieldset-border-stylesolidControls the root fieldset border style.
--fieldset-border-width0Controls the root fieldset border width.
--fieldset-disabled-opacityvar(--opacity-disabled)Controls disabled fieldset opacity.
--fieldset-gapvar(--spacing-4)Controls spacing between fieldset parts.
--fieldset-legend-border-colorvar(--color-border)Controls legend bottom border color.
--fieldset-legend-border-stylesolidControls legend bottom border style.
--fieldset-legend-border-widthvar(--border-width-sm)Controls legend bottom border width.
--fieldset-legend-colorvar(--color-foreground)Controls legend text color.
--fieldset-legend-font-sizevar(--text-lg)Controls legend font size.
--fieldset-legend-font-weightvar(--weight-semibold)Controls legend font weight.
--fieldset-legend-line-heightvar(--line-height-text-lg)Controls legend line height.
--fieldset-legend-margin0Controls legend margin.
--fieldset-legend-padding0 0 var(--fieldset-legend-padding-bottom, var(--spacing-3))Controls legend padding.
--fieldset-legend-padding-bottomvar(--spacing-3)Controls legend bottom padding.
--fieldset-margin0Controls the root fieldset margin.
--fieldset-max-widthnoneControls the root fieldset max width.
--fieldset-padding0Controls the root fieldset padding.
--fieldset-radiusvar(--radius-none)Controls the root fieldset corner radius.
--fieldset-width100%Controls the root fieldset width.

Interactive variables scoped for docs preview without changing size scale tokens.

PropertyValueDefaultDescription
--fieldset-border-colortransparentControls root fieldset border color.
--fieldset-gapvar(--spacing-4)Controls spacing between fieldset parts.
--fieldset-legend-border-colorvar(--color-border)Controls legend border color.
--fieldset-legend-colorvar(--color-foreground)Controls legend text color.
--fieldset-radiusvar(--radius-none)Controls fieldset corner radius.

Anatomy

Fieldset groups related controls under one semantic legend. Keep the visible group label in FieldsetLegend, then place related Field blocks (or composed rows like radio options) inside the same root so native fieldset semantics and disabled behavior stay consistent.

Fieldset
├─ FieldsetLegend
└─ grouped content
   ├─ Field
   │  ├─ FieldLabel
   │  ├─ FieldControl
   │  └─ FieldError
   └─ Field / FieldItem rows (optional)
<Fieldset>
  <FieldsetLegend>Billing details</FieldsetLegend>

  <Field validationMode="onBlur">
    <FieldLabel>Company</FieldLabel>
    <FieldControl required placeholder="Enter company name" />
    <FieldError match="valueMissing">Please enter company name.</FieldError>
  </Field>
</Fieldset>
PartRole
FieldsetRoot semantic group. Renders native fieldset, controls shared disabled state, and supports render.
FieldsetLegendGroup label announced by assistive technologies for all nested controls in the fieldset.

Fieldset does not have service slots such as portal, backdrop, or viewport. In most cases, keep default semantic structure and customize visible parts (Fieldset, FieldsetLegend, and nested field slots) with className and CSS variables.

Composition

Fieldset renders a native fieldset by default and forwards Base UI state, refs, className, function className, style, function style, and render. Use render when the same root needs to also be another Base UI component, such as RadioGroup.

Fieldset and FieldsetLegend are the only public parts. There are no hidden positioner, backdrop, viewport, portal, or other service slots to style through classNames; pass className directly to the part you want to customize.

<Fieldset className={styles.fieldset}>
  <FieldsetLegend className={styles.legend}>Billing details</FieldsetLegend>
</Fieldset>

The package exports Base UI state types for advanced styling callbacks:

import { type FieldsetState, type FieldsetLegendState } from 'moduix';

Examples

Disabled

Use disabled on Fieldset to prevent interaction with every native control inside the group.

Disabled account details
import {  Fieldset,  FieldsetLegend,  Field,  FieldLabel,  FieldControl,} from "moduix";export function DisabledFieldsetDemo() {  return (    <Fieldset disabled>      <FieldsetLegend>Disabled account details</FieldsetLegend>      <Field>        <FieldLabel>Email</FieldLabel>        <FieldControl defaultValue="team@example.com" />      </Field>      <Field>        <FieldLabel>Phone</FieldLabel>        <FieldControl defaultValue="+1 (555) 123-45-67" />      </Field>    </Fieldset>  );}

Radio Group

Use render to compose the fieldset semantics with another root component, such as RadioGroup.

Storage type
import {  Field,  Fieldset,  RadioGroup,  FieldsetLegend,  FieldItem,  FieldLabel,  Radio,  RadioLabel,} from "moduix";export function RadioGroupFieldsetDemo() {  return (    <Field name="storageType">      <Fieldset render={<RadioGroup defaultValue="ssd" />}>        <FieldsetLegend>Storage type</FieldsetLegend>        {storageTypes.map((item) => (          <FieldItem key={item.value}>            <FieldLabel>              <Radio value={item.value} />              <RadioLabel>{item.label}</RadioLabel>            </FieldLabel>          </FieldItem>        ))}      </Fieldset>    </Field>  );}
const storageTypes = [  { value: "ssd", label: "SSD" },  { value: "hdd", label: "HDD" },];

Custom Styles

Pass className to Fieldset, FieldsetLegend, and nested field slots when styling with CSS Modules, Tailwind CSS, or CSS-in-JS.

Styled fieldset
import {  Fieldset,  FieldsetLegend,  Field,  FieldLabel,  FieldControl,  FieldError,} from "moduix";export function StyledFieldsetDemo() {  return (    <Fieldset className={styles.customFieldset}>      <FieldsetLegend className={styles.customLegend}>        Styled fieldset      </FieldsetLegend>      <Field validationMode="onBlur" className={styles.customField}>        <FieldLabel className={styles.customLabel}>Project name</FieldLabel>        <FieldControl          required          placeholder="Maps Platform"          className={styles.customControl}        />        <FieldError className={styles.customError} match="valueMissing">          Please enter a project name.        </FieldError>      </Field>    </Fieldset>  );}
.customFieldset {  max-width: 20rem;  gap: var(--spacing-3);  padding: var(--spacing-4);  border: var(--border-width-sm) solid color-mix(in srgb, var(--color-primary) 30%, transparent);  border-radius: var(--radius-lg);}.customLegend {  border-color: color-mix(in srgb, var(--color-primary) 40%, transparent);  color: var(--color-primary);}.customField {  gap: var(--spacing-2);}.customLabel,.customError {  color: var(--color-primary);}.customControl {  border-color: color-mix(in srgb, var(--color-primary) 40%, transparent);}.customControl:focus {  outline-color: var(--color-primary);}

On this page