Skip to content
skrewww

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

PropTypeDefaultDescription
labelstring—Visible or visually hidden label associated via FormField.
size"sm" | "md" | "lg""md"Control height and typography scale.
supportingTextstring—Helper text linked with aria-describedby when no error is present.
errorstring—Error message; sets aria-invalid and aria-describedby via ValidationMessage.
requiredbooleanfalseShows required indicator and sets aria-required.
readOnlybooleanfalseRead-only state — distinct from disabled; remains focusable.
leadingIconReactNode—Optional leading icon (Figma: Show leading icon + Leading Icon).
trailingIconReactNode—Optional trailing icon (Figma: Show trailing icon + Trailing Icon).
trailingActionReactNode—Interactive trailing control such as an apply button.
disabledbooleanfalseNative 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
    />
  );
}