v3.1.0
PhoneField

The phone-number field of the text-field family.

3.1 3.1 -- 3.1.0

Overview

  • 1
    Standard
  • 2
    Without country button
  • 3
    Without contacts button
1
Description
2
3

States

The TextField state model with the phone content — and one difference: data loading is a State value here, not an overlay. Disabled and Validation are the same independent axes.

Standard

1
2
  • 1
    Empty The flag alone in Slot#1, the label centred — no code shown until the field activates.
  • 2
    Filled The code prefix and the digits stay with the floated label; the Figma staging shows the digits ungrouped (+7 7770147860).

Active

Live — click into the field: the label floats and the code appears
1
  • 1
    The Code Appears With Activity On focus the --border-active border fades in, the label floats, and the +7 prefix joins the caret — the code is part of the phone mask, so it shows exactly when input begins.

Data loading

1
  • 1
    A State Of Its Own --pattern-spin — the loader replaces the contacts button while the number is verified. Unlike TextField, data loading is a value of this set's State axis (data-ds-state="data-loading" + aria-busy).

Error

The number is too short
1
2
  • 1
    Red Border --border-error — var(--sp-s2) inside, until the next validation; the TextField contract unchanged.
  • 2
    Helper Turns Error --text-and-icon-error — the text and the error icon (Update 3.1 added the icon to this line's Helper).

Disabled

1
  • 1
    Everything Disables Together --text-and-icon-disabled on label, code, digits and the phone-book icon; both buttons carry the real disabled attribute. The flag is artwork — it dims to opacity 0.5, the value both platforms ship.

Skeleton

1
  • 1
    The TextField Skeleton --skeleton-on-white at radius var(--sp-s20) with the shimmer — the whole box, no details, identical across the family.

Anatomy

The TextField anatomy with locked phone content. Two things live OUTSIDE the component by contract: the country-code selection list (the login-screen Bottom Sheet solution, opened by the country button) and the contact picker behind the contacts button.

Description
1
2
3
4
  • 1
    Country Code Button A separate component, not part of a standard TextField — tap size var(--sp-s40), the flag at var(--sp-s24). On by default; opens the country list.
  • 2
    Code Prefix + Digits The BaseTextLine core: the selected country's code as the prefix, the digits after it — both parts of the phone mask, both --text-and-icon-primary.
  • 3
    Contacts Button The phone-book icon in the var(--sp-s48) slot. On by default; opens the user's contact list.
  • 4
    Helper The TextField Description contract — default label text is "Phone number", the Helper carries hints and the error message.

Layout

TextField's spacing model applies unchanged — box var(--sp-s56) / var(--sp-s20) (both max ×130%), the s8/s8/s0/s8/s4 gaps, var(--sp-s16) with slots off, the Helper block. Phone-specific geometry only:

Phone-specific values · RTL

dir="rtl" — the chrome mirrors; the code + digits stay LTR (base-text-line--ltr is always on)
  • Country Code Button var(--sp-s40) — the tap square (the Slot#1 geometry; the button IS the slot).var(--sp-s24) — the flag icon; the Figma binding says (max ×150%), neither platform caps it — flagged.
  • Contacts Button var(--sp-s48) — the Slot#2 square; the phone-book glyph at var(--sp-s24) (max ×150%).
  • RTL Input Stays LTR Entering a phone number in RTL remains in LTR — base-text-line--ltr is locked on; only the chrome (slots, label, Helper) mirrors.

Animation

  • 1
    The TextField Motion Contract Scale Medium owns the label float and the border fade; the shimmer and the spinner are the same tokens. Nothing is re-declared here.
  • 2
    Press Lives On The Buttons The TextField press rule named Slot#1 — this component's country-code button — as exactly the case that requires the platform-native touch feedback (ripple / Pressed colour). The field itself never pushes.
  • 3
    The Mask Is Phone-Specific Per-country formats, not the X/9 reserved characters: the code is the fixed head, the digits follow the country's rules; switching the country swaps flag, code and mask together.
Live — focus and type: digits only, ten at most (the KZ mask)

Usage

  • 1
    Phones Go Through PhoneField Login, registration, contact forms — anywhere a number is entered, the country, code and mask travel together. A bare TextField loses all three.
  • 2
    The Country List Lives Outside The component opens it (the login-screen Bottom Sheet solution) but never contains it; the contact picker behind the contacts button is external too.
  • 3
    The Number Is Personal Data Analytics never carry the entered digits — at most empty/filled, validation and country-code flags.
We'll send a confirmation code
✓ The login phone entry — country, code and mask stay in sync
✕ A bare TextField for a phone — no country, no code, no mask, free-form digits

Accessibility

Description
1
2
  • 1
    The Button Names Its Selection [Choose country, Kazakhstan +7, Button] — the action AND the current country in one announcement; the flag inside is decorative. When the country changes, so does the name.
  • 2
    Three Focus Stops Country button → the field ([Phone number, Edit box]; editing: [Editing, Phone number, +7, 7770147860]) → the contacts button ([Address book, Button]). Both buttons disable with the field.
  • Explicit for/id — The Rule This Component Created Slot#1 is a real <button> preceding the input, so an implicit <label> association would silently target it — every PhoneField box pairs for= with the input's id (recorded on TextField, shipped here).
  • Digits Read Verbatim A phone number reads digit by digit, never as a large number — the platforms guarantee it (iOS accessibilityValue, Android VerbatimTtsAnnotation, the code merged into the value). The web has no equivalent mechanism: type="tel" digits read per-digit as an AT heuristic, and the code is heard on the country button, one swipe earlier — a recorded divergence.
  • Everything Else Is TextField Error (aria-invalid + the Helper text), skeleton (aria-hidden + aria-busy), the :focus-within border as the focus ring, reduced motion at the token.