v3.2.0
TextField

Text fields let users enter text into a UI.

3.1 3.2 -- 3.2.0
Description

Overview

  • 1
    Standard
  • 2
    With slots
  • 3
    With Description
  • 4
    CustomTextField
1
2
3
Letters and digits only
4

States

The State axis is rest/active × empty/filled plus Skeleton; Disabled and Validation are independent axes that combine with it. The surface never changes — the border and the label position carry the state.

Rest

1
2
  • 1
    Rest Empty --text-and-icon-secondary — the label alone, Main Body 16/20, vertically centred; no border.
  • 2
    Rest Filled The entered text keeps the floated Compact Body label — the field remembers its content shape at rest.

Active

Live — click into the field: the border fades in, the label floats
1
  • 1
    Active Indicator --border-active — the var(--sp-s2) inside border appears from transparency on Scale Medium; it doubles as the visible focus indicator.
  • Label Floats Main Body 16/20 → Compact Body 14/16, the input line opens below on the same token. In placeholder-label mode nothing floats — the label hides on the first character instead.

Error

Hyphens are not allowed
1
2
  • 1
    Error Border --border-error — var(--sp-s2) inside; it does not disappear until the next validation, focused or not. Recorded gap: Android paints it with --text-and-icon-error instead of the border token.
  • 2
    Description Turns Error --text-and-icon-error — the text and the warning-filled icon at 16×16; the icon aligns with the first line when the text is long. Never colour alone: the text carries the error.

Disabled

Description
1
  • 1
    Everything Tints --text-and-icon-disabled — label, text, icons and description together; the fill stays --surface-on-white and the input carries the real disabled attribute. Recorded gap: Android does not render prefix/suffix at all when disabled; iOS tints them.

Skeleton

1
  • 1
    One Simple Rectangle --skeleton-on-white at radius var(--sp-s20) with the DS shimmer (--pattern-shimmer) — the whole box, no details, no Description. The same for every field type. Recorded gap: iOS draws its skeleton at var(--sp-s24) radius.

Data loading

1
  • 1
    Loader Replaces Slot#2 --pattern-spin — the s24 spinner takes the inner end slot while the field waits for the server; the loader is decorative, the container reports busy. Recorded gates diverge: iOS hides the Description and shows the loader even disabled; Android keeps the Description and suppresses the loader when disabled — flagged for a ruling.

Anatomy

A column of two blocks: the box (Slot#1 · StartText · Slot#2 in a row) and the Description below. Only the box and the label are required. The editable core inside StartText is a BaseTextLine instance — its prefix/suffix, masks and caret contract apply unchanged.

Description
1
2
3
4
  • 1
    Slot#1 Optional, var(--sp-s40) square — a DS icon only; a custom element carries its own s40 touch area.
  • 2
    StartText The floating label above the BaseTextLine input line; fills the row, long text hides beyond the boundary — no truncation.
  • 3
    Slot#2 Optional, one or two var(--sp-s48) items at var(--sp-s0) apart. Default is the info icon; shown here — the Clear Text Button (clear-filled in --text-and-icon-secondary, 3.2).
  • 4
    Description The helper line — Compact Body 14/16, multiline, with an optional s16 leading icon (3.2); one line only when its trailing-slot form is enabled.
  • The Public Master Is A Wrapper In Figma [TextField] 3.2 adds the outer margins (var(--sp-s4) / var(--sp-s16)) and swaps Type between this set and CustomTextField. Neither platform implements the wrapper — margins are the caller's duty, and so does the web.

Slot#2 · Count = Two

1
2
  • 1
    Inner Item The first var(--sp-s48) item sits next to the text — Android's endInnerSlot, iOS's trailingView; the clear button and the loader live here.
  • 2
    Outer Item The second item trails at var(--sp-s0) apart — Android's endOuterSlot, iOS's additionalView; never replaced by the loader. Each button is its own focus stop and target.

Layout

Values follow the Figma Specification frame's coefficient notation — no coefficient means the value never scales. The box is a minimum: it grows if content forces it, and the paddings compose so a missing slot leaves the spec's s16 edge.

General

Description
1
2
3
  • 1
    Box var(--sp-s56) (max ×130%) — minimum height; both platforms ship it fixed — recorded nuance.var(--sp-s20) (max ×130%) — radius.var(--sp-s8) — edge to Slot#1; var(--sp-s4) — edge to Slot#2.
  • 2
    Slots var(--sp-s40) — Slot#1 square; var(--sp-s48) — each Slot#2 item.var(--sp-s8) — slot to text, both sides; var(--sp-s0) — between two Slot#2 items.var(--sp-s16) — edge to text when a slot is off (the box's right padding steps s4 → s8).
  • 3
    Description var(--sp-s8) — box to Description; var(--sp-s16) — side paddings.var(--sp-s4) — icon to text; the icon is var(--sp-s16) square.
  • Label ↔ Text var(--sp-s0) — the floated label sits directly on the input line.
  • Figma Observation With Slot#2 hidden the set's own auto-layout composes the right edge at 12, while the Specification states var(--sp-s16) — flagged; the web and iOS follow the spec, Android composes 12.

RTL

وصف
dir="rtl" — the row, label and Description mirror; masks and amounts follow the BaseTextLine rules
  • A Variant Axis RTL is staged in the Figma set: Slot#1 leads from the right, the text right-aligns, Slot#2 trails left, the Description mirrors with its icon.
  • BaseTextLine Rules Hold Inside Input masks keep their LTR direction; amounts pin left-to-right (base-text-line--ltr).

Animation

  • 1
    Scale Medium Owns The Field The label float (16/20 ⇄ 14/16), the input line opening and the border fading in all run on var(--pattern-scale-medium-appear) / var(--pattern-scale-medium-hide) — 400ms on the standard curve. Both platforms play exactly these numbers; iOS approximates the label with a geometric scale and its Secure field plays 250ms — both flagged.
  • 2
    No Press Animation On The Field Touch animation is required only for the buttons in Slot#1 (the Phone field) and Slot#2 — Android a circular ripple, iOS the Pressed icon colour. The field itself never pushes.
  • 3
    Reduced Motion Every token zeroes at motion.css — the label and border snap, the shimmer and spinner stop; the component ships no override.
Live — focus, type, clear: every move is Scale Medium

Usage

  • 1
    One Field Type, Three Lines This component is the Text Input; Password Input and Phone Input are the sibling [PasswordField] / [PhoneField] lines assembled on the same anatomy — never rebuild them ad hoc from this one.
  • 2
    Prefix And Suffix Come From The Core Currency symbols and units of measurement are BaseTextLine prefix/suffix inside StartText — not slot content and not part of the label.
  • 3
    Customs Go Through CustomTextField A non-preset colour or layout re-points the --text-field-* slots on a Custom instance; the predefined set's values are never overridden in place.
Up to 20 kg
✓ A named field; the unit is a BaseTextLine suffix, repeated in the description
✕ A bare placeholder as the only guidance — no visible name once typing starts

Accessibility

Letters and digits only
1
2
  • 1
    One Named Focus Area The voiced preview: [Label, Helper, Double-tap to enter text] — the label names the input (aria-labelledby), the Description describes it (aria-describedby), and the whole box is a <label> so tapping anywhere focuses the field.
  • 2
    Slot Buttons Are Their Own Stops Real <button> elements named for the action — [Clear text. Button.]; decorative Slot#1 icons stay hidden. On the shipped builds: Android debounces the clicks and gates them on enabled; iOS hides the eye toggle and re-exposes it as a custom action on the combined Secure element.
  • Error Is Announced, Not Painted The Description carries the error text (already in aria-describedby) plus aria-invalid="true"; Android additionally sets the error() semantic. The red border and the 16×16 icon are the visual channel — never colour alone.
  • The Border Is The Focus Ring --border-active at var(--sp-s2) on :focus-within satisfies the visible-focus duty BaseTextLine delegates to its host — keyboard and pointer draw the same border.
  • Disabled And Skeleton Are Native The real disabled attribute on input and slot buttons; the skeleton box is aria-hidden and the loading container carries aria-busy.