Text Field

A labelled single-line text input with description and error slots.

TextField is the label, input, help text, and error message as one component. Compose them yourself only when a form needs a layout this does not support.

Variants

Filled

The default. A gray, 40px field with a small gray label, sized for dense product forms and settings.

<TextField label="Name" placeholder="Enter your name" />

Outline

A transparent, 36px field with a 1px border, an 8px radius, and a label at the same 12px size as Filled, in the primary text colour instead of gray. Focus thickens the border to the primary text colour; errors and the disabled state look as they do on Filled.

Optional
Enter your company name.
<div className="flex flex-col gap-5">
<TextField variant="outline" label="Work Email" placeholder="[email protected]" />
<TextField variant="outline" label="Website URL" placeholder="https://" isOptional />
<TextField
  variant="outline"
  label="Company Name"
  errorMessage="Enter your company name."
/>
</div>

Use one variant per form. A Select takes the same variant, so a form that mixes text fields and selects still matches. The label keeps the text you give it: Filled title-cases it, Outline does not, so a question such as "What are you interested in?" reads as written.

Examples

With description

We only use this to send receipts.
<TextField
label="Email"
placeholder="[email protected]"
description="We only use this to send receipts."
/>

label names the field, description explains it before the user makes a mistake, and errorMessage explains one after. A placeholder is not a label: it disappears on first keystroke and is invisible to some assistive tech.

Invalid

Enter a valid email address.
<TextField
label="Email"
defaultValue="not-an-email"
isInvalid
errorMessage="Enter a valid email address."
/>

Optional

Optional
<TextField label="Related PR" isOptional placeholder="https://github.com/…" />

isOptional adds an "Optional" hint on the label row, aligned to the input's end edge in a lighter gray than the label. Mark the few optional fields rather than every required one, and keep "Optional" out of the label text itself. For custom fields built from React Aria parts, FieldLabel renders the same label row.

Read-only

<TextField label="Read-Only" defaultValue="Locked value" isReadOnly />

Disabled

<TextField label="Disabled" placeholder="Unavailable" isDisabled />

validationBehavior defaults to native, so the field participates in the browser's form validation and reports on submit. Set it to aria when the form owns validation and you only want the accessible wiring.

Distinguish the two inert states: isReadOnly keeps the value readable, selectable, and submitted; isDisabled removes the field from the form and from the tab order.

Prefixes and suffixes

Prefix

<TextField label="Amount" placeholder="0.00" start={<span>$</span>} />

Suffix

<TextField label="Domain" placeholder="myapp" end={<span>.base.org</span>} />

start and end render inside the field's border. Use them for units, prefixes, and icons — not for buttons, which need their own hit target outside the input.

Leading icon

Wrap a leading icon in InputStartIcon to get the field's icon size, padding, and focus and error colours. It renders a Label, so clicking the icon focuses the input.

<TextField
aria-label="Search"
placeholder="Search"
start={
  <InputStartIcon>
    <SearchIcon />
  </InputStartIcon>
}
/>

When to use

Use TextField for single-line free text, with its label, help text, and error message. Use Filled in dense product forms and settings, and Outline in marketing forms such as the base.org contact form, where fields sit on the page background with more room around them.

Use something else when:

Usage

Do

Write a description when the requirement is not obvious from the label. Preventing the error costs the user less than recovering from it.

Don't

Use a placeholder in place of a label. It vanishes as soon as the user types, leaving no way to recall what the field was for.

Do

Pick one variant for the whole form, and set the same variant on its Selects.

Don't

Mix Filled and Outline fields in one form, or add asterisks to required fields. Mark the optional ones with isOptional instead.

Props

PropTypeDefault
autoComplete

Describes the type of autocomplete functionality the input should provide if any. See

TypestringDefault—
autoCorrect

An attribute that takes as its value a space-separated string that describes what, if any, type

TypestringDefault—
className

The CSS [className](https://developer.mozilla.org/en-US/docs/Web/API/Element/className) for the

TypeClassNameOrFunction<TextFieldRenderProps>Default—
defaultValue

The default value (uncontrolled).

TypestringDefault—
descriptionTypeReactNodeDefault—
endTypeReactNodeDefault—
enterKeyHint

An enumerated attribute that defines what action label or icon to preset for the enter key on

Type"enter" | "done" | "go" | "next" | "previous" | "search" | "send"Default—
errorMessageTypeChildrenOrFunction<FieldErrorRenderProps>Default—
inputMode

Hints at the type of data that might be entered by the user while editing the element or its

Type"none" | "search" | "text" | "tel" | "url" | "email" | "numeric" | "decimal"Default—
isDisabled

Whether the input is disabled.

TypebooleanDefault—
isInvalid

Whether the value is invalid.

TypebooleanDefault—
isOptional

Shows "Optional" on the label row, aligned to the input's end edge.

TypebooleanDefault—
isReadOnly

Whether the input can be selected but not changed by the user.

TypebooleanDefault—
isRequired

Whether user input is required on the input before form submission.

TypebooleanDefault—
labelTypeReactNodeDefault—
maxLength

The maximum number of characters supported by the input. See

TypenumberDefault—
minLength

The minimum number of characters required by the input. See

TypenumberDefault—
pattern

Regex pattern that the value of the input must match to be valid. See

TypestringDefault—
placeholderTypestringDefault—
spellCheck

An enumerated attribute that defines whether the element may be checked for spelling errors.

TypestringDefault—
startTypeReactNodeDefault—
type

The type of input to render. See

Type(string & {}) | "search" | "text" | "tel" | "url" | "email" | "password"Default'text'
validate

A function that returns an error message if a given value is invalid.

Type((value: string) => true | ValidationError | null)Default—
validationBehavior

Whether to use native HTML form validation to prevent form submission

Type"native" | "aria"Default'native'
variant

Gray 40px `filled` field, or transparent, bordered 36px `outline` field.

Type"filled" | "outline"Defaultfilled

FieldLabel

Inside a TextField or Select, FieldLabel takes the field's variant. In a custom field, pass variant to match the input styles: the exported fieldStyles, labelStyles, inputWrapperStyles, and inputStyles helpers take the same variant and default to filled.

PropTypeDefault
elementTypeTypestringDefault—
isOptional

Shows "Optional" at the end of the label row, aligned to the input's end edge.

TypebooleanDefault—
variant

Defaults to the enclosing field's variant, or `filled` outside one.

Type"filled" | "outline"Default—

InputStartIcon

PropTypeDefault
elementTypeTypestringDefault—

Accessibility

TextField wraps React Aria's TextField, which associates the label, description, and error message with the input and announces validation changes. When a field has no visible label, pass aria-label — an unlabelled input is unusable with a screen reader. In development, a TextField with no label and no aria-label logs a console warning.

The description and the "Optional" hint use fg-muted, which meets 4.5:1 contrast against the page background in light and dark themes.

Both variants show focus with a 2px ring, Filled in gray and Outline in the primary text colour, and show errors in red and in the error message, not by colour alone.

The focus ring and a leading icon's colour fade in over 150ms, and change at once when the reader prefers reduced motion.