PhoneInput

Phone number input with an international country code selector, built on InputGroup

Installation

pnpm add @wandercom/design-system-web

Usage

8 lines
import { PhoneInput } from '@wandercom/design-system-web/ui/phone-input';
import { useState } from 'react';

export function Example() {
  const [phone, setPhone] = useState('');

  return <PhoneInput defaultCountry="us" value={phone} onChange={setPhone} />;
}

Examples

Default

Basic phone input with country selector.

Loading example...

Small

Using the sm size variant.

Loading example...

With label

Phone input paired with a label.

Loading example...

Disabled

Disabled state with a pre-filled value.

Loading example...

Custom country list

Restrict the available countries using the countries prop. defaultCountries and parseCountry are re-exported from the phone input module for filtering.

Loading example...
11 lines
import {
  defaultCountries,
  PhoneInput,
  parseCountry,
} from '@wandercom/design-system-web/ui/phone-input';

const northAmerica = defaultCountries.filter((c) =>
  ['us', 'ca'].includes(parseCountry(c).iso2)
);

<PhoneInput countries={northAmerica} defaultCountry="us" />

For a flat list of ISO-2 codes, the filterCountries helper does the same filtering in one call. It pairs with the country lists in @wandercom/design-system-shared/countries:

7 lines
import { STRIPE_CONNECT_COUNTRIES } from '@wandercom/design-system-shared/countries';
import {
  filterCountries,
  PhoneInput,
} from '@wandercom/design-system-web/ui/phone-input';

<PhoneInput countries={filterCountries(STRIPE_CONNECT_COUNTRIES)} />

Props

value?:

string
Phone value in E.164 format (e.g. "+14155550123").

onChange?:

(value: string) => void
Called with E.164 phone string on change.

defaultCountry?:

CountryIso2
Default country ISO-2 code. Defaults to "us".

countries?:

CountryData[]
Restrict available countries. Defaults to all countries.

preferredCountries?:

CountryIso2[]
Countries pinned to the top of the dropdown.

size?:

"default" | "sm"
Size variant matching InputGroup sizes. Defaults to "default".

placeholder?:

string
Placeholder text for the phone number field. Defaults to "Phone number".

selectCountryLabel?:

string
Accessible label for the country selector button. Defaults to "Select country".

searchPlaceholder?:

string
Placeholder for the country search field. Defaults to "Search country or dial code...".

searchLabel?:

string
Accessible label for the country search field. Defaults to the searchPlaceholder value.

emptyLabel?:

string
Text shown when no country matches the search. Defaults to "No country found.".

disabled?:

boolean
Disable the entire input. Defaults to false.

className?:

string
Additional CSS classes for the root InputGroup.

Keyboard navigation

  • Tab moves focus to the phone number input
  • Enter or Space on the country button opens the country selector
  • and navigate countries in the dropdown
  • Enter selects the highlighted country and returns focus to the input
  • Escape closes the dropdown
  • Typing in the search field filters by country name or dial code

Accessibility

  • Country selector button has aria-label="Select country", overridable via selectCountryLabel
  • Flag images are decorative (alt=""); the country name is announced from the adjacent text in each option
  • Country search field has an accessible label, overridable via searchLabel
  • Dropdown search supports keyboard-only navigation
  • Focus is returned to the phone number input after country selection

Behavior

Country selector opens a searchable dropdown built on the Base UI Combobox. Search by country name or dial code (e.g. "+44" or "united").

Preferred countries appear at the top of the dropdown list when specified.

E.164 output means the onChange callback always emits the full international number in E.164 format (e.g. +14155550123), suitable for storage and validation.

Dial code displays between the flag and the input, matching the primary text color.

Built on InputGroup, the component inherits size variants, border states, focus ring, and disabled styling from the design system's InputGroup component.

PhoneInput