---
title: Field
description: Label, description and error for one control, wired for screen readers.
---

```tsx
import { Field, Input } from "@openperf/deft";

import { Preview } from "../../src/Preview";

export default function FieldBasic() {
  return (
    <Preview stack={true}>
      <Field.Root>
        <Field.Label>Label</Field.Label>
        <Input.Root />
        <Field.Description>Description</Field.Description>
      </Field.Root>
    </Preview>
  );
}
```

- Use one `Field.Root` for each control. Put the label above the control and the description below it.
- An [Input](/deft/components/input) or [Textarea](/deft/components/textarea) without a field needs an `aria-label`.
- Inside a [List](/deft/components/list), use `List.Field` for the label and description.

## Validation

```tsx
import { Field, Input } from "@openperf/deft";
import { useState } from "react";

import { Preview } from "../../src/Preview";

export default function FieldValidation() {
  const [invalid, setInvalid] = useState(true);

  return (
    <Preview stack={true}>
      <Field.Root invalid={invalid}>
        <Field.Label>Label</Field.Label>
        <Input.Root
          defaultValue="120"
          max={100}
          min={0}
          onChange={(event) => {
            setInvalid(!event.currentTarget.validity.valid);
          }}
          type="number"
        />
        {!invalid && <Field.Description>Description</Field.Description>}
        <Field.Error match={invalid}>Enter a value from 0 to 100.</Field.Error>
      </Field.Root>
    </Preview>
  );
}
```

- Set `invalid` on `Field.Root` from the field's validation state. An invalid field puts a red ring around its [Input](/deft/components/input).
- Render the description only while the field is valid, so the error replaces it rather than stacking below it.
- Error text says how to fix the value, not just that it is wrong.

## Switch in label

```tsx
import { Field, Switch } from "@openperf/deft";

import { Preview } from "../../src/Preview";

export default function FieldSwitch() {
  return (
    <Preview stack={true}>
      <Field.Root>
        <Field.Label>
          <Switch.Root />
          Label
        </Field.Label>
      </Field.Root>
    </Preview>
  );
}
```

Put a `Switch.Root` inside `Field.Label` so the whole label toggles the setting.

## API

| Prop | Type | Default | Description |
| - | - | - | - |
| `invalid?` | `boolean` | - | On Root. Marks the control invalid. |
| `disabled?` | `boolean` | `false` | On Root. Disables the control and fades the label. |
| `match?` | `boolean \| keyof ValidityState` | - | On Error. Shows the error when true or when the control has that validity state. |

Parts: `Root`, `Description`, `Error`, `Label`, and Base UI's `Control`, `Validity` and `Item` unchanged. Built on Base UI [Field](https://base-ui.com/react/components/field).
