v3.0.0
BaseTextLine

The basic single-line text input, according to which the other inputs are assembled. Developer-facing: designers work with the assembled fields — this core owns text entry, masking and the five colour slots, and nothing else.

3.0 3.0 -- 3.0.0

Overview

  • 1
    Plain
  • 2
    Prefix
  • 3
    Suffix
  • 4
    Input mask
1
2
3
4

States

Two independent axes — interaction (Standard, the Figma Rest · Active) × content (empty · filled) — plus the platform Disabled. BaseTextLine's only own Active signal is the caret; the visible focus treatment (border, underline, label move) is the assembled field's duty.

Standard

1
2
  • 1
    Empty --text-and-icon-secondary — the placeholder alone guides the expected format until the first character.
  • 2
    Filled --text-and-icon-primary — the entered text, with its affixes and mask formatting.

Active

Live — click into the line: the caret is the Active state
1
  • 1
    Caret --base-text-line-cursor — 1 × 20, --text-and-icon-primary by default; the platform's native caret, never re-implemented.
  • Placeholder Persists Until Typing Focus alone does not clear the placeholder — it disappears with the first character (both platforms; the mask demo under Animation shows it live).
  • The Affordance Is The Host's The web reference suppresses the input's default outline — the assembled field draws the Active border/underline. A standalone line restores a :focus-visible indicator (see Accessibility).

Disabled

1
  • 1
    Everything Tints --text-and-icon-disabled — text, placeholder and both affixes re-point together (base-text-line--disabled + the input's disabled attribute).
  • A Platform State The Figma set stages only Rest/Active × empty/filled; both platforms additionally ship enabled = false — recorded in the spec, mirrored on the web.

Anatomy

A row of three parts — only the input is required. The container hugs its content height (20, or 24 with an icon affix) and fills the host's width; the input yields width to the affixes, never the other way round.

1
2
3
  • 1
    Prefix Text or an icon before the entry — a currency symbol before a sum, a search icon before a query. Optional; never wraps or shrinks.
  • 2
    Input The one editable, focusable element — single line, fills the remaining width. Carries the placeholder and the caret.
  • 3
    Suffix Units, currency or context after the entry — kg, m², %. Optional; the same never-truncate rule.
  • Affix Visibility Follows Input Activity The Figma behaviour contract: an empty, unfocused line shows only its placeholder; affixes appear with input activity and stay once filled. iOS shows the prefix on focus or content (plus an always-visible flag); on Android and the web the show/hide policy is the assembled field's call.

Layout

The container fills the host's width and hugs its content height; every field padding belongs to the assembled field. Values follow the Figma Specification frame's coefficient notation — no coefficient means the value never scales with the SP mode.

General

1
2
  • 1
    Icon Affix var(--sp-s24) (max ×150%) — the affix glyph box.iOS draws affix icons at var(--sp-s20) — a recorded platform deviation.
  • 2
    Item Spacing var(--sp-s4) — the gap between prefix, input and suffix; an SP unit on both platforms, so it scales with the mode.
  • Paddings var(--sp-s0) — horizontal padding.var(--sp-s0) — vertical padding; the host field owns the field paddings.
  • Sizing Width — auto-layout fill (Flexible on iOS, FillMax on Android, flex: 1 on the input on the web). Height — hug: 20 on the Main Body line, 24 with an icon affix.
  • Typography Body/Main Body for input, placeholder, prefix and suffix — var(--text-body-main-body-size) / var(--text-body-main-body-line-height), set together. An assembled field may hand an affix its own style (the price field's big amount) — iOS then corrects the affix baseline.

Text alignment

left — by default
center
right
  • Three Values, Left By Default base-text-line--center / base-text-line--right re-point text-align on the input; the bare root is start-aligned.
  • A Web-Only Knob Today The Figma Specification declares the axis; neither mobile platform exposes an alignment parameter yet — a recorded gap.

RTL

dir="rtl" — the row mirrors, the prefix stays logically first
base-text-line--ltr — an amount stays LTR inside RTL chrome
  • The Row Mirrors dir="rtl" on the host reverses the row and flips the default alignment left → right; the prefix stays logically first.
  • Masks Keep LTR Only the alignment changes — the direction of input masks remains as in LTR (the Figma RTL block).
  • Amounts Pin LTR base-text-line--ltr — an amount reads left-to-right in every locale; only the surrounding chrome mirrors (iOS isInputForcedLeftToRight).

Animation

  • 1
    No Motion Of Its Own BaseTextLine declares no motion tokens — the only moving part is the platform caret's native blink, never re-implemented. State transitions (label float, border colour) belong to the assembled fields.
  • 2
    Masks Format Live Typing consumes the mask left to right: restricted symbols are filtered out, literals self-insert, the caret never gets stuck. Phone numbers and dates use a separate mask implementation — X/9 do not apply there.
  • 3
    Reduced Motion Nothing to reduce — no token, no override.
Live — type: mask XXX9999 (X = letter/digit, 9 = digit) filters as you go

Usage

  • 1
    Assemble, Don't Ship Bare BaseTextLine is the input core of TextField, PhoneField, PriceField, search and code inputs. It has no label, border, helper or error affordance — standalone in product UI it is an unnamed, unframed line.
  • 2
    Affixes Carry Context, The Name Carries Meaning A currency prefix or a unit suffix clarifies the entry, but the accessible name comes from the field's label — never from the affix or the placeholder.
  • 3
    One Line Only Multi-line entry is Textarea's contract; phone numbers and dates belong to the PhoneField line with its own mask rules.
Trip price
✓ The core of an assembled field — the host owns label, border, paddings
✕ Standalone in product UI — no name, no frame, no focus affordance

Accessibility

1
2
  • 1
    One Focus Area The input is the one focusable, named element — Android role EditText, iOS trait Textfield, web <input type="text">. What is announced follows the state: the placeholder while empty, the value when filled.
  • 2
    Affixes Are Silent iOS hides every affix kind (accessibilityHidden); Android hides icon affixes (contentDescription = null — a text affix has no explicit exclusion today, flagged); the web marks them aria-hidden="true". Meaning carried by an affix is repeated in the accessible name — "Price in US dollars", not a bare "Price" next to a hidden "USD".
  • The Name Comes From The Host The assembled field's label names the input; a standalone line needs an explicit aria-label. Placeholder is not a name. Trap: iOS today force-assigns accessibilityLabel = placeholder, making the placeholder the persistent VoiceOver name — flagged to the iOS owners.
  • Focus Ring And Target Are The Host's Duty The base suppresses the default outline and hugs 20–24 of height — the assembled field draws the Active state and pads the target. A standalone use restores a :focus-visible outline of var(--sp-s2) in var(--text-and-icon-primary) and pads the tappable area to var(--sp-s44).
  • Disabled Is Native The real disabled attribute plus the colour re-point — never aria-disabled on a live input, never a readonly masquerade.