Field
A set of components to build accessible form fields with labels, descriptions, and validation messages.
We'll use this email to send you system notifications.
import * as React from 'react'; import { Field } from 'gnome-ui/field'; import { Input } from 'gnome-ui/input'; export function FieldDefault() { return ( <Field.Root className="flex w-full max-w-sm flex-col gap-2"> <Field.Label className="text-sm font-medium text-foreground"> Email </Field.Label> <Field.Control > <Input className="flex h-10 w-full rounded-xl border border-input bg-card px-3 py-2 text-sm text-foreground shadow-sm transition-colors focus-visible:border-primary focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring disabled:cursor-not-allowed disabled:opacity-50 data-[invalid]:border-destructive data-[invalid]:focus-visible:outline-destructive" placeholder="you@example.com" type="email" /> </Field.Control> <Field.Description className="text-xs text-muted-foreground"> We'll use this email to send you system notifications. </Field.Description> </Field.Root> ); }
Anatomy
import { Field } from 'gnome-ui/field'; <Field.Root> <Field.Label /> <Field.Control /> <Field.Description /> <Field.Error> <Field.Validity /> </Field.Error> </Field.Root>
Examples
With Validation Error
The Field component handles form validation automatically. It manages the validity state and shows the Field.Error component when the validation fails. Try submitting the form below with an empty or short value.
import * as React from 'react'; import { Field } from 'gnome-ui/field'; import { Input } from 'gnome-ui/input'; import { AlertCircle } from 'lucide-react'; export function FieldWithError() { return ( <form onSubmit={(e) => { e.preventDefault(); // Form submission logic }} className="w-full max-w-sm" > <Field.Root className="flex w-full flex-col gap-2" validate={(value) => { if (!value) return 'Username is required.'; if (String(value).length < 4) return 'Must have at least 4 characters.'; return null; }} > <Field.Label className="text-sm font-medium text-foreground"> Username </Field.Label> <Field.Control > <Input className="flex h-10 w-full rounded-xl border border-input bg-card px-3 py-2 text-sm text-foreground shadow-sm transition-colors focus-visible:border-primary focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring disabled:cursor-not-allowed disabled:opacity-50 data-[invalid]:border-destructive data-[invalid]:focus-visible:outline-destructive" placeholder="Ej: ubuntu_user" /> </Field.Control> <Field.Error className="flex items-center gap-1.5 text-sm font-medium text-destructive"> <Icons.AlertCircle className="size-4 shrink-0" /> <Field.Validity> {(state) => state.error || 'Invalid input'} </Field.Validity> </Field.Error> <button type="submit" className="mt-2 inline-flex h-9 items-center justify-center rounded-xl bg-primary px-4 text-sm font-medium text-primary-foreground transition-colors hover:brightness-95 focus-visible:outline focus-visible:outline-2 focus-visible:outline-ring active:brightness-90" > Save </button> </Field.Root> </form> ); }
FieldControl
The form control to label and validate.
Renders an <input> element.
You can omit this part and use any Base UI input component instead. For example, Input, Checkbox, or Select, among others, will work with Field out of the box.
Documentation: Base UI Field
API reference
Root
Groups all parts of the field.
Renders a <div> element.
Root Props:
| Prop | Type | Default | Description |
|---|---|---|---|
| name | string | - | Identifies the field when a form is submitted.
Takes precedence over the name prop on the <Field.Control> component. |
| actionsRef | RefObject<Field.Root.Actions | null> | - | A ref to imperative actions.* validate: Validates the field when called. |
| dirty | boolean | - | Whether the field's value has been changed from its initial value. Useful when the field state is controlled by an external library. |
| touched | boolean | - | Whether the field has been touched. Useful when the field state is controlled by an external library. |
| disabled | boolean | false | Whether the component should ignore user interaction.
Takes precedence over the disabled prop on the <Field.Control> component. |
| invalid | boolean | - | Whether the field is invalid. Useful when the field state is controlled by an external library. |
| validate | ((value: unknown, formValues: Form.Values<string, any>) => string | string[] | Promise<string | string[] | null> | null) | - | A function for custom validation. Return a string or an array of strings with
the error message(s) if the value is invalid, or null if the value is valid.
Asynchronous functions are supported, but they do not prevent form submission
when using validationMode="onSubmit". |
| validationMode | Form.ValidationMode | 'onSubmit' | Determines when the field should be validated.
This takes precedence over the validationMode prop on <Form>.* onSubmit: triggers validation when the form is submitted, and re-validates on change after submission. |
onBlur: triggers validation when the control loses focus.onChange: triggers validation on every change to the control value. | | validationDebounceTime |number|0| How long to wait betweenvalidatecallbacks ifvalidationMode="onChange"is used. Specified in milliseconds. | | className |string \| ((state: Field.Root.State) => string \| undefined)| - | CSS class applied to the element, or a function that returns a class based on the component’s state. | | style |CSSProperties \| ((state: Field.Root.State) => CSSProperties \| undefined)| - | - | | render |ReactElement \| ((props: HTMLProps, state: Field.Root.State) => ReactElement)| - | Allows you to replace the component’s HTML element with a different tag, or compose it with another component.Accepts aReactElementor a function that returns the element to render. |
Root Data Attributes:
| Attribute | Type | Description |
|---|---|---|
| data-disabled | - | Present when the field is disabled. |
| data-valid | - | Present when the field is valid. |
| data-invalid | - | Present when the field is invalid. |
| data-dirty | - | Present when the field's value has changed. |
| data-touched | - | Present when the field has been touched. |
| data-filled | - | Present when the field is filled. |
| data-focused | - | Present when the field control is focused. |
Label
An accessible label that is automatically associated with the field control.
Renders a <label> element.
Label Props:
| Prop | Type | Default | Description |
|---|---|---|---|
| nativeLabel | boolean | true | Whether the component renders a native <label> element when replacing it via the render prop.
Set to false if the rendered element is not a label (e.g. <div>).This is useful to avoid inheriting label behaviors on <button> controls (such as <Select.Trigger> and <Combobox.Trigger>), including avoiding :hover on the button when hovering the label, and preventing clicks on the label from firing on the button. |
| className | string | ((state: Field.Root.State) => string | undefined) | - | CSS class applied to the element, or a function that returns a class based on the component’s state. |
| style | CSSProperties | ((state: Field.Root.State) => CSSProperties | undefined) | - | - |
| render | ReactElement | ((props: HTMLProps, state: Field.Root.State) => ReactElement) | - | Allows you to replace the component’s HTML element
with a different tag, or compose it with another component.Accepts a ReactElement or a function that returns the element to render. |
Label Data Attributes:
| Attribute | Type | Description |
|---|---|---|
| data-disabled | - | Present when the field is disabled. |
| data-valid | - | Present when the field is in valid state. |
| data-invalid | - | Present when the field is in invalid state. |
| data-dirty | - | Present when the field's value has changed. |
| data-touched | - | Present when the field has been touched. |
| data-filled | - | Present when the field is filled. |
| data-focused | - | Present when the field control is focused. |
Control
The form control to label and validate.
Renders an <input> element.You can omit this part and use any Base UI input component instead. For example,
Input, Checkbox,
or Select, among others, will work with Field out of the box.
Control Props:
| Prop | Type | Default | Description |
|---|---|---|---|
| defaultValue | string | number | string[] | - | - |
| onValueChange | ((value: string, eventDetails: Field.Control.ChangeEventDetails) => void) | - | Callback fired when the value changes. Use when controlled. |
| className | string | ((state: Field.Root.State) => string | undefined) | - | CSS class applied to the element, or a function that returns a class based on the component’s state. |
| style | CSSProperties | ((state: Field.Root.State) => CSSProperties | undefined) | - | * |
| render | ReactElement | ((props: HTMLProps, state: Field.Root.State) => ReactElement) | - | Allows you to replace the component’s HTML element
with a different tag, or compose it with another component.Accepts a ReactElement or a function that returns the element to render. |
Control Data Attributes:
| Attribute | Type | Description |
|---|---|---|
| data-disabled | - | Present when the field is disabled. |
| data-valid | - | Present when the field is in valid state. |
| data-invalid | - | Present when the field is in invalid state. |
| data-dirty | - | Present when the field's value has changed. |
| data-touched | - | Present when the field has been touched. |
| data-filled | - | Present when the field is filled. |
| data-focused | - | Present when the field control is focused. |
Description
A paragraph with additional information about the field.
Renders a <p> element.
Description Props:
| Prop | Type | Default | Description |
|---|---|---|---|
| className | string | ((state: Field.Root.State) => string | undefined) | - | CSS class applied to the element, or a function that returns a class based on the component’s state. |
| style | CSSProperties | ((state: Field.Root.State) => CSSProperties | undefined) | - | - |
| render | ReactElement | ((props: HTMLProps, state: Field.Root.State) => ReactElement) | - | Allows you to replace the component’s HTML element
with a different tag, or compose it with another component.Accepts a ReactElement or a function that returns the element to render. |
Description Data Attributes:
| Attribute | Type | Description |
|---|---|---|
| data-disabled | - | Present when the field is disabled. |
| data-valid | - | Present when the field is in valid state. |
| data-invalid | - | Present when the field is in invalid state. |
| data-dirty | - | Present when the field's value has changed. |
| data-touched | - | Present when the field has been touched. |
| data-filled | - | Present when the field is filled. |
| data-focused | - | Present when the field control is focused. |
Item
Groups individual items in a checkbox group or radio group with a label and description.
Renders a <div> element.
Item Props:
| Prop | Type | Default | Description |
|---|---|---|---|
| disabled | boolean | false | Whether the wrapped control should ignore user interaction.
The disabled prop on <Field.Root> takes precedence over this. |
| className | string | ((state: Field.Root.State) => string | undefined) | - | CSS class applied to the element, or a function that returns a class based on the component’s state. |
| style | CSSProperties | ((state: Field.Root.State) => CSSProperties | undefined) | - | - |
| render | ReactElement | ((props: HTMLProps, state: Field.Root.State) => ReactElement) | - | Allows you to replace the component’s HTML element
with a different tag, or compose it with another component.Accepts a ReactElement or a function that returns the element to render. |
Error
An error message displayed if the field control fails validation.
Renders a <div> element.
Error Props:
| Prop | Type | Default | Description |
|---|---|---|---|
| match | boolean | 'valid' | 'badInput' | 'customError' | 'patternMismatch' | 'rangeOverflow' | 'rangeUnderflow' | 'stepMismatch' | 'tooLong' | 'tooShort' | 'typeMismatch' | 'valueMissing' | - | Determines whether to show the error message according to the field’s
ValidityState.
Specifying true will always show the error message, and lets external libraries
control the visibility. |
| className | string | ((state: Field.Error.State) => string | undefined) | - | CSS class applied to the element, or a function that returns a class based on the component’s state. |
| style | CSSProperties | ((state: Field.Error.State) => CSSProperties | undefined) | - | - |
| render | ReactElement | ((props: HTMLProps, state: Field.Error.State) => ReactElement) | - | Allows you to replace the component’s HTML element
with a different tag, or compose it with another component.Accepts a ReactElement or a function that returns the element to render. |
Error Data Attributes:
| Attribute | Type | Description |
|---|---|---|
| data-disabled | - | Present when the field is disabled. |
| data-valid | - | Present when the field is in valid state. |
| data-invalid | - | Present when the field is in invalid state. |
| data-dirty | - | Present when the field's value has changed. |
| data-touched | - | Present when the field has been touched. |
| data-filled | - | Present when the field is filled. |
| data-focused | - | Present when the field control is focused. |
Validity
Used to display a custom message based on the field’s validity.
Requires children to be a function that accepts field validity state as an argument.
Validity Props:
| Prop | Type | Default | Description |
|---|---|---|---|
| children | ((state: Field.Validity.State) => ReactNode) | - | A function that accepts the field validity state as an argument.```jsx |