Field
Label, description, and error for any form control, wrapping the Base UI Field. Drop a Bones control inside and the accessibility wiring and validation state happen automatically.
Playground
Flip Invalid to watch the error replace the description and the input turn red at the same time; click the label to prove it focuses the input.
We only use this for receipts.
States
Invalid and disabled are the ones you set; touched, dirty, and filled arrive on their own as the user works, and focus rings the control inside on every focus.
We only use this for receipts.
Managed by your workspace admin.
Beyond the manual invalid prop, fields validate from native constraints (required, type, pattern) or a custom validate function on the root. Each error can target one condition with match, so the message fits the mistake:
<FieldRoot name="email">
<FieldLabel>Email</FieldLabel>
<Input type="email" required />
<FieldError match="valueMissing">Email is required.</FieldError>
<FieldError match="typeMismatch">That doesn't look like an email.</FieldError>
</FieldRoot>Styling states
The field and the control inside both carry the state (data-invalid, data-touched, data-dirty, data-disabled), so custom styling never needs JavaScript:
.ub-field[data-invalid] .ub-field-label {
color: var(--ub-danger);
}Props
Each part passes the full Base UI API through. The essentials:
| Prop | Type | Default | Description |
|---|---|---|---|
FieldRoot.name | string | – | The field's name, forwarded to the control inside. |
FieldRoot.invalid | boolean | – | Forces the invalid state, for server-side errors. |
FieldRoot.disabled | boolean | false | Disables the control and dims the label. |
FieldRoot.validationMode | "onBlur" | "onChange" | "onSubmit" | "onSubmit" | When validation runs; overrides the Form-level setting for this field. |
FieldRoot.validationDebounceTime | number | 0 | Milliseconds to wait before validating on change. |
FieldRoot.validate | (value, formValues) => string | string[] | null | Promise<...> | – | Custom validation, sync or async; return the error message(s) or null. Receives the other fields' values too. |
FieldError.match | boolean | keyof ValidityState | – | Show this error only for one validity condition; true forces it on. |
Agent instructions
Working with a coding agent? Paste this into its context, or point it at llms.txt for the whole library.
FieldRoot, FieldLabel, FieldDescription, FieldError, from @usebones/react.
- Put one Bones control inside FieldRoot (Input, Checkbox, Select, Switch); label wiring, aria-describedby, and validation state are automatic.
- FieldRoot: name, disabled, invalid (for server errors), validate(value).
- FieldError renders only while invalid; match="valueMissing" (or any ValidityState key) binds it to one condition. A forced invalid on the root needs match (true) on the error for it to show.
- Inside a Field, prefer FieldDescription and FieldError over the control's own hint and invalid props.
- Restyle in CSS via .ub-field, .ub-field-label, .ub-field-description, .ub-field-error, and [data-invalid], [data-touched], [data-dirty], [data-filled], [data-disabled] on the root and the control. Tokens only.