Forms
Text Input
Text Input is a single-line text entry for short, free-form data such as names, emails, or search terms.
State × Size — 15 variants
stableReact AvailableFigma AvailableDocs Partial
- React last updated
- 2026-07-11
- Documentation last updated
- 2026-06-01
- Accessibility target
- WCAG 2.2 AA (target)
- Version
- 1.0.0
Known open questions
- FormField composes label/helper/error internally — confirm parity with Figma Form Field Wrapper split.
- Hover state token mapping not explicitly documented — uses semantic/border/strong on hover.
- Trailing action slot is a documentation convenience; confirm Figma trailing icon property semantics.
Purpose
Single-line text entry for short, free-form data (names, emails, search terms, general form fields).
Variants and states
default · error · disabled
When to use
Any single-line free-text field. Text Input is a complete field: it renders its own label, supporting text, required indicator and error (it composes Form Field internally), so pass `label`, `supportingText`, `required` and `error` as props. Do not wrap it in Form Field or add a separate label or Validation Message for the same field.
When not to use
Multi-line content (use Textarea). A fixed set of choices (use Select). Search-specific fields (use Search Field).
Accessibility
Must have a visible or aria-labelled <label> in code — never rely on placeholder text alone. Error state needs aria-invalid and aria-describedby. Focused state uses semantic/focus-ring at 2px outside-aligned stroke.
Common mistakes
Using placeholder text as a substitute for a real label. Wrapping Text Input in Form Field or adding a second label or Validation Message for the same field (it already renders both). Passing your own aria-describedby or aria-invalid, which replaces the wiring Text Input provides. Not visually distinguishing Disabled from Default strongly enough.
Properties
State × Size as variants. Value (text). Show leading/trailing icon (booleans) + Leading/Trailing Icon (instance-swap).
When should I use Text Input instead of Textarea?
Use Text Input for short, single-line values such as names, email addresses, codes, or general form fields. Use Textarea when users need to enter content that can span multiple lines, such as descriptions, comments, or messages.
When should I use Text Input instead of Search Field?
Use Text Input for general form data. Use Search Field when the input's primary purpose is searching or filtering content and the search-specific leading icon and optional clear action are appropriate.
Tokens used
component/radius/controlsemantic/border/defaultsemantic/border/strongsemantic/focus-ringsemantic/action/dangersemantic/surface/default
Component API
| Prop | Type | Default | Description |
|---|---|---|---|
| label | string | — | Visible or visually hidden label associated via FormField. |
| size | "sm" | "md" | "lg" | "md" | Control height and typography scale. |
| supportingText | string | — | Helper text linked with aria-describedby when no error is present. |
| error | string | — | Error message; sets aria-invalid and aria-describedby via ValidationMessage. |
| required | boolean | false | Shows required indicator and sets aria-required. |
| readOnly | boolean | false | Read-only state — distinct from disabled; remains focusable. |
| leadingIcon | ReactNode | — | Optional leading icon (Figma: Show leading icon + Leading Icon). |
| trailingIcon | ReactNode | — | Optional trailing icon (Figma: Show trailing icon + Trailing Icon). |
| trailingAction | ReactNode | — | Interactive trailing control such as an apply button. |
| disabled | boolean | false | Native disabled input with non-opacity-only visual treatment. |
React example
Copy React example
import { TextInput } from "@/components/ui/TextInput";
export function Example() {
return (
<TextInput
label="Email address"
type="email"
placeholder="you@example.com"
supportingText="Used for account notifications only."
required
/>
);
}