# Text Inputs

Source: https://payloadcms.com/docs/ui-components/text-inputs

`TextInput` and `TextareaInput` combine native text controls with Payload's label, description, validation, and read-only field presentation. Use them when building a Custom Field that manages its own value.

## Import

```tsx
import { TextareaInput, TextInput } from '@payloadcms/ui'
```

## TextInput

**Implementation**

```tsx
const [value, setValue] = useState('Quarterly report')

<TextInput
  description="Displayed as the document title."
  label="Title"
  onChange={(event) => setValue(event.target.value)}
  path="title"
  required
  value={value}
/>
```

**Styling**

Target the TextInput field wrapper and native input to customize its surface, outline, and focus treatment.

```css
.field-type.text input {
  background: var(--theme-input-bg);
  border: 1px solid var(--theme-elevation-250);
  border-radius: 6px;
}

.field-type.text input:focus {
  border-color: var(--theme-elevation-500);
}
```

- `--theme-input-bg`: Input surface inherited from the theme.
- `border`: Input outline.
- `border-radius`: Input corner radius.

`TextInput` is controlled. Pass the current string through `value` and update it from the native change event.

Set `hasMany` to render Payload's sortable multi-value text control instead of a native input.

## TextareaInput

**Implementation**

```tsx
const [value, setValue] = useState(
  'A concise summary for the project dashboard.',
)

<TextareaInput
  description="Keep the summary brief and useful."
  label="Summary"
  onChange={(event) => setValue(event.target.value)}
  path="summary"
  rows={4}
  value={value}
/>
```

**Styling**

Style the native textarea inside Payload’s field wrapper while retaining its label, description, and validation layout.

```css
.field-type.textarea textarea {
  background: var(--theme-input-bg);
  border: 1px solid var(--theme-elevation-250);
  border-radius: 6px;
  resize: vertical;
}

.field-type.textarea textarea:focus {
  border-color: var(--theme-elevation-500);
}
```

- `--theme-input-bg`: Textarea surface inherited from the theme.
- `border`: Textarea outline.
- `border-radius`: Textarea corner radius.
- `resize`: Allowed manual resize direction.

Use `rows` to establish the initial height. The value remains controlled by the surrounding Custom Field.

## Common props

These props are shared by both inputs unless noted otherwise.

| Prop          | Type                      | Default | Description                                    |
| ------------- | ------------------------- | ------- | ---------------------------------------------- |
| `path` \*     | `string`                  | —       | Identifies the field and connects its UI.      |
| `value`       | `string`                  | `''`    | Supplies the controlled value.                 |
| `onChange`    | `ChangeEventHandler`      | —       | Receives native input changes.                 |
| `label`       | `StaticLabel`             | —       | Displays Payload's field label.                |
| `description` | `StaticDescription`       | —       | Displays helper text beneath the input.        |
| `placeholder` | `string \| LabelFunction` | —       | Displays translated placeholder text.          |
| `required`    | `boolean`                 | `false` | Displays the required marker.                  |
| `readOnly`    | `boolean`                 | `false` | Disables editing and applies read-only styles. |
| `showError`   | `boolean`                 | Form    | Displays the current validation error.         |
| `BeforeInput` | `ReactNode`               | —       | Inserts content before the native control.     |
| `AfterInput`  | `ReactNode`               | —       | Inserts content after the native control.      |
| `rows`        | `number`                  | —       | Sets the TextareaInput row count.              |
| `hasMany`     | `boolean`                 | `false` | Enables TextInput's multi-value mode.          |

_\* An asterisk denotes that a prop is required._

## Custom field usage

Inside a Custom Field, connect the input to Payload's form state with `useField`:

```tsx
'use client'

import { TextInput, useField } from '@payloadcms/ui'

export function CustomTextField({ field, path }) {
  const { setValue, showError, value } = useField<string>({ path })

  return (
    <TextInput
      label={field.label}
      onChange={(event) => setValue(event.target.value)}
      path={path}
      required={field.required}
      showError={showError}
      value={value}
    />
  )
}
```

## Provider requirements

The Admin Panel supplies the translation and form contexts used by the built-in label, description, and validation components. Use these inputs inside a Payload Custom Field, or provide equivalent contexts when rendering them elsewhere.
