Field
Connect a control with its label, help and validation.
Visible to your team.
Installation
pnpm dlx shadcn@4.18.0 add @siteplane/inputComplete the one-time setup first. Registry JSON lists source files and dependencies.
For this page’s examples, also install:
pnpm dlx shadcn@4.18.0 add @siteplane/action-icons @siteplane/button @siteplane/checkbox @siteplane/combobox @siteplane/input-group @siteplane/select @siteplane/textareaUsage
import { Field, FieldLabel } from "@/siteplane/components/field";
import { Input } from "@/siteplane/components/input";
<Field>
<FieldLabel>Name</FieldLabel>
<Input />
</Field>;Composition
Field
├── FieldLabel
├── Input or FieldControl
├── FieldDescription
├── FieldError
└── FieldValidity (optional)A label or a description wraps a long unbroken value, such as a URL or a German compound, within the width of the field, so the field never grows past its container.
Custom validation
Field owns validation timing and error association. Return null for a valid value or an error string; this example validates on blur.
Used in the project URL.
FieldError animates by itself, with no code on your side. A message expands with a fade instead of pushing the form down, and when it clears it collapses while it still shows its last message. The space between the control and the error opens with it. While a message leaves it is hidden from assistive technology. Reduced motion shows and hides the message at once. FieldError uses the Motion component, which installs with the Field.
A native reset of the form around the Field, from a reset button or form.reset(), returns the Field to how it was before the first submit: its error collapses, and its touched and dirty marks clear. In a Form, the fields validate again on the next submit.
Floating label
Set labelPlacement="floating" and the label sits inside the field; it moves to the top on focus or once there is a value. It works with Input, Textarea, Select, a single-select Combobox and Autocomplete, and with trailing actions such as the show-password button of an Input Group. Floating fields take no leading icon, so every label and value starts on the same line; a field that needs a leading icon uses the top label. Floating fields have one size, 48 px.
Required fields
Set required on the control to make a field required. To mark it, add requiredIndicator to the Field: its label then shows a red asterisk while the control is required, above the field or inside a floating label. Whether a form marks its required fields is your choice per form. The control's own required stays the only source, so there is nothing to keep in sync, and screen readers hear the control's required state, not the asterisk.
To warn when a required field is left empty, set validationMode="onBlur" on the Field or the Form and add a FieldError for valueMissing. The message shows once the field is left empty and clears while the missing value is typed; a submit shows every message at once. The contact details form puts both together.
<Field requiredIndicator validationMode="onBlur">
<FieldLabel>First name</FieldLabel>
<Input required />
<FieldError match="valueMissing">Enter your first name.</FieldError>
</Field>Error tooltip
In a floating Field, FieldError shows its message in a red bubble beside the control instead of below it, so nothing in the form moves when it appears; elsewhere it reveals the line below the field. Set variant to choose either way: variant="tooltip" beside a top label, or variant="inline" for the line below a floating field. The bubble shows its message while you are in the field; other invalid fields show the invalid frame, so one bubble shows at a time, like the browser's own validation bubble. A field left empty turns invalid, and its bubble shows when you return to it, until the value is valid. A submit with invalid fields moves focus to the first of them, which shows its bubble. The bubble points at the control from its end side, or from below on a narrow screen. It never takes the pointer or focus, and it stays the control's error description for screen readers. The contact details form uses it.
<Field labelPlacement="floating" requiredIndicator validationMode="onBlur">
<FieldLabel>First name</FieldLabel>
<Input required />
<FieldError match="valueMissing">Enter your first name.</FieldError>
</Field>Select field
Field labels and describes a Select trigger. Pass items so the trigger shows the selected option's label.
Choose where your data is stored.
Checkbox field
Wrap a Checkbox in FieldLabel to label it; the FieldDescription is announced with it. The checkbox sits on the first line of the label, also when the label wraps, and the description and the error start under the label text. For the options of a checkbox or radio group, use FieldItem as shown on Fieldset. An option with a description of its own puts the control beside a column of FieldLabel and FieldDescription, as on Radio Group.
A short summary of new features, sent once a month.
API reference
The styled parts add labelPlacement and requiredIndicator on Field and variant on FieldError; everything else comes from Base UI Field. The following contracts are central to integration:
| Prop | Type | Default | Description |
|---|---|---|---|
Field. | top | floating | top | Draws the label above the control, or inside it, where it floats up on focus or once there is a value. |
Field. | boolean | false | Marks the label with a red asterisk while the control is required. |
Field. | string | unset | Field name used for submission and external form errors. |
Field. | boolean | false | Disables the field and its control. |
Field. | onSubmit | onBlur | onChange | onSubmit / Form | When validation runs; a field override wins over Form. |
Field. | (value, formValues) => error | null | Promise | unset | Custom validation; asynchronous validation does not block onSubmit submission. |
Field. | number | 0 | Milliseconds between onChange validation callbacks. |
Field. | boolean | uncontrolled | External state overrides. |
Field. | ref | unset | Exposes validate(). |
Field | boolean | validity key | foundation matching | true always shows children; otherwise match the validation error. |
Field | inline | tooltip | tooltip in a floating Field, inline otherwise | inline reveals the message below the control; tooltip shows it in a red bubble beside the control while the field has focus, so nothing moves and other invalid fields show the invalid frame. |
FieldLabel labels the control; FieldDescription supplies associated help;
FieldError displays validation messages. FieldItem scopes a label/control
pair. FieldControl and FieldValidity are direct foundation exports;
FieldPrimitive exposes the namespace. FieldValidity children receive validity,
error, errors, value and initialValue. All styled parts accept string className
and foundation refs/render props; no styled callback-class evaluation is added.
FieldError renders for validity errors, Form errors, or when match is true.
For an application-controlled error, set invalid on Field and match on
FieldError.
The Field spaces its parts by --field-gap (8 px). FieldError reads the same
value, so to change the spacing set it on the Field, for example
className="[--field-gap:calc(var(--spacing)*3)]", instead of using a gap-* utility.
Usage notes
Field is installed with Input; it is not a separate registry item. Use a real server validation boundary for persisted data. An invalid style alone neither validates nor explains an error.
Make a field required with required on its control. To show that, use requiredIndicator rather than an asterisk in the label text: the Field draws it only while the control is required. Name what is missing in the FieldError, such as “Enter your first name.”
A floating field shows its error as a tooltip by default; any other field reveals the line below it. Use the tooltip beside a top label as well where a layout shift hurts, such as a compact form with several fields in a row; in a single column, the line below reads more calmly. The tooltip shows its message while you are in the field; other invalid fields show the invalid frame.
With a floating label:
- A placeholder shows only after focus, under the floated label.
- Floating fields take no leading icon, so every label and value starts on the same line. A field that needs a leading icon uses the top label: an Input Group that opens with an addon, an Input with
insetStart, and a Combobox or Autocomplete with astartAddonkeep the label above the control even in a floating Field. Trailing actions, such as show password, clear and the Select caret, are fine. - Use the top label for text prefixes and suffixes such as
https://, and for Number Field, a multi-select Combobox with chips, Date Field, Time Field and OTP Field. They keep the label above the control even in a floating Field. - Descriptions stay below the field; errors show as a tooltip by default.