skrewww

Forms

Phone Number Field

Phone Number Field pairs a country/dial-code selector with a phone number input — UI pattern only, not SMS verification or carrier lookup.

State (Default/Focused/Error/Disabled) — 4 variants

betaReact AvailableFigma AvailableDocs Partial
React last updated
2026-09-14
Documentation last updated
2026-09-14
Accessibility target
WCAG 2.2 AA (target)
Version
0.1.0-beta

Known open questions

  • Figma flag is a generic two-stripe placeholder — React keeps it decorative (aria-hidden); country identity comes from Select option text.
  • Default country list is illustrative (12 entries) — pass `countries` for production datasets.
  • No national formatting engine — sanitization only allows digits and common phone punctuation.

Live preview

Country Select + type=tel number input. Flag is a decorative placeholder; country identity is the Select label.

Surface
Shape

Interactive

Mobile number

UI pattern only — not SMS verification or carrier lookup.

Value: US /

Default with international number

Contact phone

Error

Mobile number

Enter a valid phone number.

Disabled

Mobile number

Read-only

Mobile number

Purpose

Phone Number Field is a compound UI control pairing a country/dial-code selector with a phone number input as two adjacent bordered controls. It is a visual/input pattern only — not SMS verification, carrier lookup, or reachability checks.

Anatomy

PhoneNumberField = fieldset/legend + Country Selector (decorative flag placeholder + Select dial-code) + Number Input (type=tel) + optional supporting/error text.

Variants and states

default · focused · error · disabled

When to use

When documenting or collecting an international phone number where the dialing country matters. Override `countries` with your production country list.

When not to use

When you need OTP/SMS verification, number ownership confirmation, or carrier validation — use a dedicated verification service. For a plain national number with no country selector, use Text Input `type="tel"`.

Accessibility

fieldset + legend for the group; country Select and number input each have their own accessible names. Flag placeholder is decorative (aria-hidden); country identity comes from Select option text (name + dial code). Number input is type=tel with autocomplete=tel.

Keyboard behavior

Tab moves between country Select and phone number input. Select opens listbox with arrow keys; number input uses standard text editing.

Common mistakes

Treating the flag as the accessible country label. Assuming the default country list is complete. Treating sanitization as phone verification. Using type=number. Logging or persisting entered numbers from the design-system component.

Properties

Figma: State + Dial Code / Value text. React: label, country/defaultCountry/onCountryChange, value/defaultValue/onValueChange, countries, countryLabel/numberLabel, placeholder, disabled, readOnly, required, error, supportingText.

Does this verify the phone number?

No. It does not send SMS, check ownership, look up carriers, or confirm reachability. It is a UI input pattern only.

Are the flags real national flags?

No. Figma and React use a generic two-stripe placeholder. Accessible country identity is the Select option label (name + dial code).

Tokens used

component/radius/controlsemantic/border/defaultsemantic/focus-ringsemantic/text/danger

Known limitation

Flag is a generic two-stripe placeholder, not real national flags. Default country list is illustrative (12). No national formatting engine — digits and common punctuation (+ spaces () . -) are allowed; no E.164 ownership claim. /r deferred to CE-3. Does not send network requests or verify numbers.

Component API

PropTypeDefaultDescription
labelstringVisible fieldset legend for the compound control.
countrystringControlled country option value (e.g. ISO alpha-2).
defaultCountrystringUncontrolled initial country option value.
onCountryChange(country: string) => voidFires when the selected country changes.
valuestringControlled phone number string (sanitized punctuation allowed).
defaultValuestringUncontrolled initial phone number string.
onValueChange(value: string) => voidFires with the sanitized phone number after edits/paste.
countriesPhoneCountryOption[]Country options ({ value, dialCode, label }). Defaults to a small illustrative list.
countryLabelstring"Country"Accessible name for the country selector.
numberLabelstring"Phone number"Accessible name for the phone number input.
placeholderstring"Phone number"Placeholder for the number input.
disabledbooleanfalseDisables country selector and number input.
readOnlybooleanfalseRead-only number input; country selector is non-editable.
requiredbooleanfalseMarks the group and both controls required.
errorstringError message; sets invalid chrome on both controls.
supportingTextstringHelp text when no error is present.

React example

Copy React example
import { useState } from "react";
import { PhoneNumberField } from "@/components/ui/PhoneNumberField";

export function Example() {
  const [country, setCountry] = useState("US");
  const [value, setValue] = useState("");
  return (
    <PhoneNumberField
      label="Mobile number"
      country={country}
      onCountryChange={setCountry}
      value={value}
      onValueChange={setValue}
      supportingText="UI pattern only — not SMS verification or carrier lookup."
    />
  );
}