A text field that allows a user to enter a plain text value with a keyboard.
import { TextField } from "@opengovsg/oui"<TextField label="Full name" />The TextField component provides a single-line text input with built-in label, description, and error message support. It is built on React Aria's TextField.
If the component does not have a visible label (by passing a label prop), an aria-label or aria-labelledby prop must be passed instead to identify it to assistive technology.
Provide clear instructions to users with labels and descriptions.
Use the inputProps.placeholder to show placeholder text.
Combine isInvalid and errorMessage props to show validation errors.
Use the size prop to change the size of the text field. Defaults to "md".
Use the value and onChange props to control the text field value programmatically.
Current value: (empty)
Use the isDisabled prop to disable the text field.
Use the isReadOnly prop to make the text field read-only. The value can be selected but not modified.
TextField supports React Aria's form validation system:
isRequired, minLength, maxLength, pattern, or type (e.g., "email", "url") for native HTML validation. Errors display after the user commits a value or submits the form.validate prop to provide a function that returns an error message string, or null/true if valid.isInvalid prop with errorMessage for immediate feedback as the user types.validationBehavior prop controls enforcement — "native" (default) prevents form submission when invalid, while "aria" only marks the field via ARIA attributes and allows submission.TextField supports the following event handlers, inherited from React Aria's TextField:
onFocus / onBlur — Called when the input gains or loses focus.onFocusChange — Called when the focus state changes, receiving a boolean.onChange — Called when the text value changes, receiving the new string value.onCopy / onCut / onPaste — Called on clipboard operations.onCompositionStart / onCompositionEnd — Called during IME composition for internationalized text input.onKeyDown / onKeyUp — Called on keyboard events.onSelect — Called when text is selected within the input.<input> element for full browser and assistive technology support.aria-labelledby and aria-describedby.aria-label or aria-labelledby prop must be set.You can customize the TextField component by passing custom Tailwind CSS classes to the component slots via the classNames prop.
| Prop | Type | Default | Description |
|---|---|---|---|
label | React.ReactNode | - | The label for the text field |
description | React.ReactNode | - | The description text shown below the field |
errorMessage | React.ReactNode | ((validation: ValidationResult) => string) | - | The error message to display when validation fails |
value | string | - | The current value (controlled) |
defaultValue | string | - | The default value (uncontrolled) |
onChange | (value: string) => void | - | Callback fired when the value changes |
type | "text" | "email" | "password" | "search" | "tel" | "url" | "text" | The type of the input element |
size | "xs" | "sm" | "md" | "md" | The size of the component |
variant | "outline" | "unstyled" | "outline" | The visual variant of the input |
isDisabled | boolean | false | Whether the field is disabled |
isReadOnly | boolean | false | Whether the field is read-only |
isRequired | boolean | false | Whether the field is required |
isInvalid | boolean | false | Whether the field should display as invalid |
minLength | number | - | The minimum number of characters required |
maxLength | number | - | The maximum number of characters allowed |
pattern | string | - | A regular expression the value must match |
validate | (value: string) => ValidationError | true | null | undefined | - | Custom validation function |
autoComplete | string | - | Hints for browser autocomplete |
validationBehavior | "native" | "aria" | "native" | Whether to use native HTML form validation or ARIA-based validation |
name | string | - | The name of the input, used when submitting a form |
onFocus | (e: FocusEvent) => void | - | Called when the input receives focus |
onBlur | (e: FocusEvent) => void | - | Called when the input loses focus |
onFocusChange | (isFocused: boolean) => void | - | Called when the focus state changes |
inputProps | Partial<InputProps> | - | Additional props to pass to the input element |
classNames | SlotsToClasses<"base" | "label" | "input" | "description" | "error"> | - | Custom CSS classes for component slots |