Text Input

Molecule

Single-line input with label, optional leading and trailing icon slots, and helper caption. Three sizes (lg 48 / md 40 / sm 32), eight states (Default · Hover · Focus · Filled · Success · Warning · Error · Disabled), and three variants (Default text, Tags input that hosts .tag chips, OTP code input). Values from Figma node 2260-4637.

When to use

✅ Do
  • Use for short, single-line free-text entry (name, email, search, phone number)
  • Always show a visible label above the input — never rely on placeholder alone
  • Use the Error state with a helper message explaining what went wrong
  • Use the Success state to confirm valid input in real-time (e.g. available username)
  • Use the Tags variant when users need to enter multiple values (chips) in one field
  • Use OTP variant for verification code inputs — one digit per cell
❌ Don't
  • Use for multi-line content — use Text Area instead
  • Use placeholder text as the only label — placeholders disappear on focus
  • Use the Error state before the user has interacted with the field
  • Use more than one trailing icon — choose the most contextually relevant one
  • Use a Text Input for selecting from a list — use Dropdown instead

DigiLawyer Patterns

No additional product-specific patterns for Text Input.

Anatomy

A Text Input is composed of a label, an input field wrapper, optional icon slots, and a helper caption. The wrapper is shared with Text Area and Upload Media.

Helper text

  1. 1Label.input-field-label. Always visible above the field. Never replaced by placeholder.
  2. 2Wrapper.input-field. Shared with Text Area and Upload Media. Carries the state class (e.g. .input-field-error).
  3. 3Shell.input (<div>). Contains the icon slots and native input. Handles hover, focus, and filled states via CSS.
  4. 4Leading icon.input-leading. Optional. Use for context (search, user, calendar).
  5. 5Native input — bare <input type="text"> inside the shell. Font weight 400 always.
  6. 6Trailing icon.input-trailing. Optional. Use for actions (clear, show/hide password) or status.
  7. 7Caption.input-field-caption. Optional helper text or error message below the field.

Default

The minimal input is a .input-field wrapper with three children: .input-field-label, the .input shell (containing optional leading icon + native <input> + optional trailing icon), and .input-field-caption. The shell handles Hover, Focus, and Filled states automatically via :hover, :focus-within, and :has(input:not(:placeholder-shown)).

Caption

HTML
<div class="input-field">
  <label class="input-field-label" for="i1">Label</label>
  <div class="input">
    <span class="input-leading"><svg></svg></span>
    <input id="i1" type="text" placeholder="Placeholder">
    <span class="input-trailing"><svg></svg></span>
  </div>
  <p class="input-field-caption">Caption</p>
</div>

Variants

Three variants. Default is a single line of typed text. Tags wraps the shell to flow lines of .tag chips alongside the editable input — use for multi-token entry like email recipients or category pickers. OTP is a row of single-character cells for verification codes.

Caption

Label Label

Caption

Caption

Sizes

Three sizes per Figma: .input-lg (48px), default md (40px), .input-sm (32px). All use Body 1 typography (16/24); sm drops to Body 2 (14/20). Icons scale 24/24/16 px. Label and caption use Caption 1 (12/16) in all sizes.

States

Eight states. Hover / Focus / Filled are driven by native CSS (:hover, :focus-within, :has(input:not(:placeholder-shown))) — pointer or keyboard-focus to preview. Success / Warning / Error change only the caption colour (chrome stays neutral so the field never screams). Disabled uses either the wrapper class or native disabled on the <input>. .is-hover, .is-focus, and .is-filled force the visual at rest for documentation.

Caption

Caption

Caption

Caption

Caption

Caption

Caption

Caption

Full matrix

3 sizes × 8 states for the Default variant, mirroring Figma 1:1 (24 cells). Each cell shows the canonical pattern: leading icon · placeholder · trailing icon, with label above and caption below.

Large · 48
Medium · 40
Small · 32
Default

Caption

Caption

Caption

Hover

Caption

Caption

Caption

Focus

Caption

Caption

Caption

Filled

Caption

Caption

Caption

Success

Caption

Caption

Caption

Warning

Caption

Caption

Caption

Error

Caption

Caption

Caption

Disabled

Caption

Caption

Caption

Accessibility

Built on a native <input> element — all standard keyboard and screen reader behaviour is implicit.

Attribute / BehaviourValueNotes
Label association<label for="id">Always associate the visible label with the input via for / id. Never use placeholder as the only label.
Keyboard — focusTab / Shift+TabMoves focus into and out of the input
Error statearia-invalid="true"Set when the field has a validation error. Pair with aria-describedby pointing to the helper error message.
Helper messagearia-describedby="helper-id"Links the input to its helper/error text so screen readers announce it on focus
Requiredrequired or aria-required="true"Communicate required fields both visually and programmatically
Disableddisabled HTML booleanRemoves from tab order. Use sparingly — prefer read-only for content that should be visible but not editable.
Autocompleteautocomplete="email" etc.Set the correct autocomplete hint so browsers and password managers can fill values correctly

API

Class / attrOnDescription
.input-field<div>Wrapper for the whole field — column flex with 4px gap between label / shell / caption.
.input-field-label<label>Above the shell. Caption 1 (12/16), --fw-medium. Pair its for attribute with the input's id.
.input-field-caption<p>Below the shell. Caption 1 (12/16), --fw-regular. Carries the success/warning/error colour via the wrapper state modifier.
.input<div>The shell — flex row containing the leading icon, the native <input>, and the trailing icon. 40px tall (md default), Body 1 typography, 8px radius. Handles Hover / Focus / Filled via native pseudo-classes.
.input-lg.inputLarge — 48px tall.
.input-sm.inputSmall — 32px tall, Body 2 (14/20) typography, 16px icons.
.input-leading<span>Leading icon slot. Wrap inline SVG; sized 24×24 (16×16 in sm).
.input-trailing<span>Trailing icon slot. Mirror of .input-leading.
.input-tags.inputTags variant — wraps and hosts .tag chips inline with the editable input.
.input-otp<div>OTP variant — a row of single-character inputs (not a shell). Compose with .input-lg / .input-sm for size.
.input-field-success.input-fieldCaption colour shifts to --input-success-caption (green).
.input-field-warning.input-fieldCaption colour shifts to --input-warning-caption (yellow).
.input-field-error.input-fieldCaption colour shifts to --input-error-caption (red).
.input-field-disabled / disabled.input-field / <input>Sets the disabled visual. Prefer the native HTML disabled attribute on the <input> — the shell adapts via :has().
.is-hover / .is-focus / .is-filled.inputDocumentation helpers — force the corresponding state at rest for the Full matrix. Not needed in production code.