A styled text input field.

TextField

Usage

  • Use TextField for short, freeform text such as names or email addresses.
  • Use TextArea instead for longer, multi-line text such as descriptions or messages.
  • Use JsonField instead to validate JSON input within a textarea.
  • Use Search instead for search-specific input.
  • Provide a visible label (label) so users understand the purpose of the field at a glance.
  • Provide an accessible label (ariaLabel) when a visible label isn't possible.
  • Never use a placeholder in place of a visible label.

Types

  • Text (type="text") — the default. Use for names, emails, and other short-form text.
  • Password (type="password") — masks input and adds a toggle button to unmask and mask it.

Appearance

  • Medium (size="md") — the default size, suitable for most use cases.
  • Small (size="sm") — for dense layouts and smaller viewports.
  • Leading icon (icon) — renders to the left of the field text. Use to emphasize the field's meaning, such as denoting search.

Behaviors

  • Base, hover, focus, and active states follow standard form-control styling; focus adds the standard 2px focus ring and updates the border color.
  • Active state (isActive) — applies the active styling programmatically.
  • Disabled state (isDisabled) — blocks all interaction and updates the background and text color.
  • Loading state (isLoading) — shows a spinner inside the field while a background job runs.
  • Danger state (isInvalid with error) — applies danger styling and renders the error message below the field.
  • Clear button (isClearable with onClear) — resets the field to its empty state. The button is hidden while the field is empty.
  • Password visibility toggle — renders automatically on type="password" fields and swaps its icon to reflect the current visibility state.

Content

  • Write labels as clear, concise nouns or noun phrases describing the data the field expects. Never use instructional phrases as a label.
  • Leave placeholder empty for most fields — a blank field reads more clearly as unfilled.
  • Use placeholders to show example text and its expected format. Never repeat the label as the placeholder.
  • Write description text as short, complete sentences giving hints, formatting guidance, or constraints.
  • Write errors as direct instructions naming the problem and how to resolve it. Never write vague errors such as "Invalid input", and never use "please".

Implementation Notes

  • label, description, and error accept rich content in place of a plain string: React takes a ReactNode directly; Ember takes the :label, :description, and :error named blocks. Use this for labels with icons or optional indicators, and for descriptions or errors with inline links.
  • description and error both render below the field when both are set. Only the aria-describedby wiring changes: it points at the error and drops the description id once an error is present.
  • Setting error alone applies the invalid styling; isInvalid is not required alongside it.
  • isClearable requires onClear — the clear button does not render without both. It is also hidden when isDisabled is set.
  • shouldShowPasswordVisibilityToggle defaults to true and only applies to type="password". Set it to false to hide the toggle.
  • iconColor defaults to "subtle" and is forced to "disabled" when the field is disabled.
  • Passing value without onChange or onInput renders an uncontrolled field — the value is applied as the input's default.
  • The component throws an accessibility error at render when none of label, ariaLabel, or ariaLabelledby is provided.
  • elementBefore and elementAfter render custom content inside the input wrapper: elementBefore in the leading slot after any icon, elementAfter in the trailing slot after the loading spinner, clear button, and password-visibility toggle. In Ember, pass a component or use the :elementBefore / :elementAfter named blocks.
  • unsafe_leftSectionComponent and unsafe_rightSectionComponent are deprecated. Use elementBefore and elementAfter instead.
  • size values "medium" and "small" are deprecated. Use "md" and "sm".
  • unsafe_isLegacy is deprecated — components already render in the target style by default.
  • shouldAllowAutofill defaults to false, which disables browser autofill and password managers. Set it to true for fields where autofill is wanted.
  • unsafe_inputWrapperClassName applies additional classes to the element wrapping the input; wrapperRef (React) and wrapperModifier (Ember) reach that same element.
  • Ember invocation is <PlumaTextField> with @argName args. Splattributes land on the input element, so pass container classes through @className rather than class.

On this page