Devie UI

Description text

The Field component extends Base UI's Field. It is an essential building block for text inputs, providing labels, descriptions, and most importantly, validation and error display management. Fields will be typically used within a Form component that coordinates across multiple Fields.

Installation

Here is the component implementation code that you can copy to your project:

// https://base-ui.com/react/components/field
 
import { Field as BaseField } from "@base-ui-components/react/field";
import clsx from "clsx";
import { AlertCircle } from "lucide-react";
import type { ReactNode } from "react";
import styles from "./Field.module.scss";
 
interface RootProps extends BaseField.Root.Props {
  className?: string;
}
 
function Root({ className, ...props }: RootProps) {
  return (
    <BaseField.Root className={clsx(styles.root, className)} {...props} />
  );
}
 
interface LabelProps extends BaseField.Label.Props {
  className?: string;
}
 
function Label({ className, ...props }: LabelProps) {
  return (
    <BaseField.Label className={clsx(styles.label, className)} {...props} />
  );
}
 
interface ControlProps extends BaseField.Control.Props {
  className?: string;
}
 
function Control({ className, ...props }: ControlProps) {
  return (
    <BaseField.Control
      className={clsx(styles.control, className)}
      {...props}
    />
  );
}
 
interface DescriptionProps extends BaseField.Description.Props {
  className?: string;
}
 
function Description({ className, ...props }: DescriptionProps) {
  return (
    <BaseField.Description
      className={clsx(styles.description, className)}
      {...props}
    />
  );
}
 
interface ItemProps extends BaseField.Item.Props {
  className?: string;
}
 
function Item({ className, ...props }: ItemProps) {
  return (
    <BaseField.Item className={clsx(styles.item, className)} {...props} />
  );
}
 
interface ErrorProps extends BaseField.Error.Props {
  children?: ReactNode;
  className?: string;
}
 
function ErrorField({ children, className, ...props }: ErrorProps) {
  return (
    <BaseField.Error className={clsx(styles.error, className)} {...props}>
      {children ? (
        <>
          <AlertCircle
            style={{ width: "16px", height: "16px" }}
            strokeWidth={1}
          />
          {children}
        </>
      ) : null}
    </BaseField.Error>
  );
}
 
const Field = {
  Root,
  Label,
  Control,
  Description,
  Item,
  Error: ErrorField,
  Validity: BaseField.Validity,
};
 
export default Field;

Use Cases

Simple fields

Compose fields by combining subcomponents: a standalone input, an input with a label, a complete field with description, or a field displaying an error state. Labels are automatically associated with inputs for accessibility.

Description text

Error message

Basic validation with HTML constraints

You can use native HTML5 validation attributes like required, minLength, pattern, and type. Use Field.Error with the match prop to display messages based on the browser's ValidityState.

Standard client-side input validation

For most cases, the best way to add client-side input validation is to use the validate prop on Field.Root. This allows you to define custom validation rules for each input:

  • validate — A function that receives the input value and returns an error message string (or array of strings), or null if valid. Supports async functions for server-side checks.
  • validationMode — Determines when validation runs: "onSubmit" (default, validates on form submit and revalidates on change after), "onBlur" (validates when the input loses focus), or "onChange" (validates on every change).
↓ validationMode="onChange" — validates as you type
↓ validationMode="onBlur" — validates when you leave the field
↓ validationMode="onSubmit" — validates on form submission

Server-side validation and Forms

Typically, Fields are orchestrated within a Form component, allowing you to set up an onFormSubmit callback that triggers client-side or server-side validation. For advanced form state management, Base UI integrates seamlessly with TanStack Form and React Hook Form.