Field

Fields represent an individual section of a form containing an associated control and label, as well as any description or validation messages.

Give FeedbackBundle Size

Your name will be visible on your profile.

index.tsx

Installation

Base UI components are all available as a single package.

npm install @base-ui-components/react

Once you have the package installed, import the component.

import { Field } from '@base-ui-components/react/field';

Anatomy

Fields are implemented using a collection of related components:

<Field.Root>
  <Field.Control />
  <Field.Label />
  <Field.Description />
  <Field.Error />
  <Field.Validity />
</Field.Root>

Labeling and descriptive help text

All Base UI input components are aware of Base UI's Field component. The label and description are automatically wired to these components when placed inside a Field.Root:

<Field.Root>
  <Checkbox.Root>
    <Checkbox.Indicator />
  </Checkbox.Root>
  <Field.Label>My checkbox</Field.Label>
  <Field.Description>My description</Field.Description>
</Field.Root>

When using a custom component which is not aware of Base UI's Field, use Field.Control:

<Field.Root>
  <Field.Control />
  <Field.Label>My input</Field.Label>
  <Field.Description>My description</Field.Description>
</Field.Root>

The render prop allows you to pass a custom component or tag, different from the default of input:

<Field.Control render={<select />} />

Validation

When adding native HTML validation props like required or pattern, Field.Error renders error messages inside of it automatically:

<Field.Root>
  <Field.Label>My input</Field.Label>
  <Field.Control required />
  <Field.Error />
</Field.Root>

The children by default is the browser's native message, which is automatically internationalized. You may pass custom children instead:

<Field.Root>
  <Field.Control required />
  <Field.Error>Field is required</Field.Error>
</Field.Root>

Individual constraint validation failures

When there are multiple HTML validation props, you can target individual validity state failures using the match prop to render custom messages:

<Field.Root>
  <Field.Control required pattern="[a-zA-Z0-9]+" />
  <Field.Error match="valueMissing">Field is required</Field.Error>
  <Field.Error match="patternMismatch">Only alphanumeric characters allowed</Field.Error>
</Field.Root>

For the list of supported match strings, visit ValidityState on MDN.

Custom validation

In addition to the native HTML constraint validation, custom validation can be used by specifying a validate function on Field.Root. It receives the control's value as its argument, and returns an error string or array of error strings if the field is invalid, or null otherwise.

<Field.Root
  validate={(value) =>
    value === 'password' ? 'Cannot literally use `password` as your password.' : null
  }
>
  <Field.Control type="password" />
  <Field.Label>Password</Field.Label>
  <Field.Error />
</Field.Root>

For Base UI input components, value represents the component's value type, while for native elements, it is always the native element.value DOM property. Attach a ref to the Control element and access it to read its state inside the validate function for further control as an alternative if necessary.

To customize the rendering of multiple messages, you can use the Validity subcomponent:

<Field.Root
  validate={(value) => {
    const errors = [];
    if (value.length < 8) {
      errors.push('Password must be at least 8 characters long.');
    }
    if (value === 'password') {
      errors.push('Cannot literally use `password` as your password.');
    }
    return errors;
  }}
>
  <Field.Control type="password" />
  <Field.Label>Password</Field.Label>
  <Field.Error>
    <ul>
      <Field.Validity>
        {(state) => state.errors.map((error) => <li key={error}>{error}</li>)}
      </Field.Validity>
    </ul>
  </Field.Error>
</Field.Root>

The Validity subcomponent enables rendering custom JSX based on the state parameter, which contains the following properties:

It can be placed anywhere inside Field.Root, including other Field subcomponents.

Controlled validity

When the invalid prop is applied to Field.Root, the Field is placed into an invalid state regardless of client-side validation. In this state, a given Field.Error message can be forced to be shown by specifying a forceShow prop.

This is useful for server-side error messages, or displaying errors initially during SSR phase.

const [serverErrors, setServerErrors] = React.useState({
  email: false,
});

return (
  <Field.Root invalid={serverErrors.email}>
    <Field.Control type="email" required />
    <Field.Error match="valueMissing">Client-side only error message</Field.Error>
    <Field.Error match="typeMismatch" forceShow={serverErrors.email}>
      Client + server-side error message
    </Field.Error>
    <Field.Error forceShow={serverErrors.email}>Server-side only message</Field.Error>
  </Field.Root>
);

The show prop is for client-side validation, while the forceShow prop is for server-side validation. Both can be combined together to share the same error message.

Performing an email validity check on the server:

On the client, standard email validation is performed. On the server, we check a blocklist of email domains: the blocked domain is @example.com.

UnstyledFieldServerError.tsx

Errors shown initially for password validation:

  • Password must be at least 8 characters long.
  • Password must contain at least 2 uppercase letters.
  • Password must contain at least 2 unique symbols from the set [!@#$%^&*].
UnstyledFieldPassword.tsx

Realtime and async validation

validationMode="onChange" reports the validity of the control on every change event instead of blur:

<Field.Root validationMode="onChange">

The validate function can also be async by returning a promise, enabling inline server-side validation through network requests.

In the demo below, the taken names are admin, root, and superuser — every other name is available. For demonstration purposes, a fake network request that takes 500ms is initiated to mimic a trip to the server to check for availability on the back-end.

Handle availability checker

Enter a name

UnstyledFieldAsync.tsx

The onChange validation is debounced by 500ms to avoid firing a network request on every keystroke by specifying the validationDebounceTime prop:

<Field.Root validationMode="onChange" validationDebounceTime={500}>

Styling

The [data-valid] and [data-invalid] style hooks determine if the field is valid or not:

<Field.Root>
  <Field.Control required className="FieldControl" />
</Field.Root>
.FieldControl[data-invalid] {
  color: red;
}

[data-touched] is applied if the field has been "touched": blurred after being interacted with, or submitted if pressing Enter on an input.

.FieldControl[data-touched] {
  color: red;
}

[data-dirty] is applied if the field's value has been changed from its initial one.

.FieldControl[data-dirty] {
  color: orange;
}

API Reference

FieldRoot

The foundation for building custom-styled fields.

PropTypeDefaultDescription
classNameunionClass names applied to the element or a function that returns them based on the component's state.
disabledboolfalseWhether the field is disabled. Takes precedence over the disabled prop of the Field.Control component.
invalidboolDetermines if the field is forcefully marked as invalid.
namestringThe field's name. Takes precedence over the name prop of the Field.Control component.
renderunionA function to customize rendering of the component.
validatefuncFunction to custom-validate the field's value. Return a string or array of strings with error messages if the value is invalid, or null if the value is valid. The function can also return a promise that resolves to a string, array of strings, or null.
validationDebounceTimenumber0The debounce time in milliseconds for the validate function in onChange phase.
validationModeenum'onBlur'Determines when validation should be triggered.

FieldLabel

A label for the field's control.

PropTypeDefaultDescription
classNameunionClass names applied to the element or a function that returns them based on the component's state.
renderunionA function to customize rendering of the component.

FieldDescription

A description message for the field's control.

PropTypeDefaultDescription
classNameunionClass names applied to the element or a function that returns them based on the component's state.
renderunionA function to customize rendering of the component.

FieldError

Displays error messages for the field's control.

PropTypeDefaultDescription
classNameunionClass names applied to the element or a function that returns them based on the component's state.
forceShowboolDetermines whether the error message should be shown regardless of the field's client validity.
matchenumDetermines whether the error message should be shown when it matches a given property of the field's ValidityState.
renderunionA function to customize rendering of the component.

FieldControl

The field's control element. This is not necessary to use when using a native Base UI input component (Checkbox, Switch, NumberField, Slider, Radio Group etc).

PropTypeDefaultDescription
classNameunionClass names applied to the element or a function that returns them based on the component's state.
onValueChangefuncCallback fired when the value changes. Use when controlled.
renderunionA function to customize rendering of the component.

FieldValidity

Render prop component that provides the field's validity state and value to its children.

PropTypeDefaultDescription

Contents