Skip to content

Fields

We'll never share your email.

<div class="field">
<label class="field-label" for="email">Email</label>
<input
id="email"
type="email"
class="input"
placeholder="you@example.com"
aria-describedby="email-desc"
/>
<p id="email-desc" class="field-description">
We'll never share your email.
</p>
</div>
<div class="field">
<label class="field-label" for="email-required" data-required>Email</label>
<input id="email-required" type="email" class="input" required />
</div>
<div class="field">
<label class="field-label" for="email-asterisk"
>Email <span class="asteriskField">*</span></label
>
<input id="email-asterisk" type="email" class="input" required />
</div>

required on the Field only marks the label. Set it on the control too, or nothing validates.

Must be at least 3 characters.

<div class="field">
<label class="field-label" for="username">Username</label>
<input
id="username"
class="input"
required
minlength="3"
placeholder="At least 3 characters"
/>
<p class="field-error">Must be at least 3 characters.</p>
</div>
<div class="field field-row">
<input type="checkbox" role="switch" class="switch" />
<label class="field-label" for="notify">Email me about new orders</label>
</div>

Username is required.

Must be at least 3 characters.

<div class="field">
<label class="field-label" for="username-multi">Username</label>
<input
id="username-multi"
class="input"
required
minlength="3"
placeholder="At least 3 characters"
/>
<p class="field-error">Username is required.</p>
<p class="field-error">Must be at least 3 characters.</p>
</div>
Part Renders Class
Field <div> field
Field.Container <div> field
Field.Label <label> field-label
Field.Description <p> field-description
Field.Error <div>, only when matching field-error
Prop Type Default
label ReactNode
description ReactNode
error ReactNode
required boolean false
inline boolean false
classNames slots

Wraps Base UI Field, which earns the component its place: it generates the control’s id, points the label’s for at it, wires aria-describedby to both the description and the error, and mirrors the browser’s ValidityState onto the root as [data-invalid] — the hook the CSS uses to redden every control inside. name, validationMode and validate come from there.

Field with label / description / error covers the ordinary case, rendering the parts in the right order around children. Field.Container renders only the .field box and leaves you to place the parts, which an irregular layout calls for. It is also the form to use when each message ties to a specific ValidityState key through Field.Error’s match, since the error prop is one message shown for any failure. Both render the same element; only the amount of assembly differs. See the .Container escape hatch.

inline puts the control before the label on one row, the layout for a switch or a lone checkbox. classNames covers label, description, error. Plus native <div> attributes.

Class Effect
field Vertical stack, 0.375rem gap; long tokens break rather than overflow
field-row Lays the field out on one line instead, 0.75rem gap
field-label text-sm medium
field-description text-xs muted
field-error text-xs in the danger colour
asteriskField Danger-coloured *, for template generators that emit their own

None of the wiring is automatic here: set for on the label, id on the control, and aria-describedby pointing at the description and the error. [data-required] on the label appends a red asterisk, the same result as an inline asteriskField span — pick whichever your templates emit.

[data-invalid] on the field reddens the border of a contained input, textarea, select, file-input, and unchecked checkbox or radio, and rings an unchecked switch. React sets it from validation; in vanilla, add it server-side alongside the field-error text.

Controls that belong inside a field: Inputs, Textareas, Selects, Checkboxes, Radios, Switches, File inputs, Number inputs.