Mark Ku's Blog
React Component · npm

React Intl Phone Number

A drop-in international phone number input — one <PhoneNumberInput> gives you a searchable flag / country-code dropdown, E.164 in/out, leveled validation, and a themeable modern look.

View on npmView on GitHub
Free · Open Source (MIT)🧩 TypeScript · antd-free · Lightweight
App.tsx
import PhoneNumberInput from 'react-intl-phone-number'
import 'react-intl-phone-number/styles.css'

<PhoneNumberInput
  value={phone}
  onChange={setPhone}
  defaultCountry="TW"
  validationLevel="mobile-strict"
/>
Live & interactive
+886
912 345 678
+886912345678

Key Features

International phone input that's correct, beautiful, and ready out of the box

🌍

Searchable country dropdown

Pick a country by flag or calling code (+886, +66…), with preferred countries on top and A→Z ordering across all ~245 regions.

🔢

E.164 in/out

value / onChange always speak E.164 (+886912345678), so you can store it or send it to your backend with no extra conversion.

Leveled validation

Three levels — strict / mobile-strict / loose — apply pattern or length checks to mobile and landline independently, with onValidityChange reporting live.

🎨

Themeable CSS

Every value is a CSS variable on .ripn-root with single-class, low-specificity selectors, so Tailwind utilities win without !important; or target parts via classNames.

🧩

Framework-agnostic

No antd, no UI-framework lock-in. The core validation logic (react-intl-phone-number/core) runs standalone on a backend or in forms — no React required.

🌐

Built-in i18n

Override every string with a messages object or your own t(key, vars) — reuse your existing react-i18next locale files as-is.

📞

Google-grade number rules

Parsing, formatting, and validation come from Google-maintained google-libphonenumber, kept in sync with each country's telecom authority — e.g. Malaysia's variable-length mobile numbers, or the UK / Canada re-allocating ranges for anti-fraud — so you track real-world changes without hand-maintaining regex.

⌨️

Controlled, accessible, error-aware

A fully controlled component with onBlur / disabled / inputRef and aria-label; after blur it can auto-show the validation error (showError → red border, role="alert", aria-invalid), plus a number-format hint tooltip.

Live Demo

This is the real <PhoneNumberInput> installed on this site — go ahead and type.

Validation level

Loading…
onChange output (E.164)
(nothing entered yet)
Validity
(nothing entered yet)
google-libphonenumber error code
— (valid or empty)

Switch the validation level and try numbers from different countries — after blur the built-in error appears under the field (showError). Below, the E.164 output, validity, and google-libphonenumber's raw error code update live. (Rendered with the package's default light theme.)

Three Validation Levels

Choose whether mobile and landline get pattern checks or just length checks.

strict

Both mobile and landline must fully match the country's pattern — the strictest, for when precision matters.

mobile-strict

Mobile is pattern-validated; landline is length-checked only. A common middle ground.

loose

Both mobile and landline are length-checked only — the most permissive, for forms that just need something plausible.

Quick Start

Install, import the stylesheet, then drop in a <PhoneNumberInput>.

Install

Required peers

npm i react react-dom google-libphonenumber

react / react-dom you likely already have; google-libphonenumber is a required peer to install separately (it powers parsing and validation).

Usage

import { useState } from 'react'
import PhoneNumberInput from 'react-intl-phone-number'
import 'react-intl-phone-number/styles.css'

export default function App() {
  const [phone, setPhone] = useState('')
  return (
    <PhoneNumberInput
      value={phone}
      onChange={setPhone}
      defaultCountry="TW"
      validationLevel="mobile-strict"
    />
  )
}

Common Props

Everything is fully typed, with IDE autocompletion.

valuestring

Controlled E.164 value (e.g. +886912345678); empty string when cleared.

onChange(value: string) => void

Emits E.164 when the number satisfies validationLevel; a partial value otherwise, empty string when there are no digits after the calling code.

validationLevelstrict | mobile-strict | loose

Required. Decides what counts as valid for both emit and the standalone validator.

defaultCountryCountryCode (e.g. "TW")

Initial country; changing it adopts the new country and clears the number.

onValidityChange(isValid: boolean) => void

Fires when the computed validity (per validationLevel) changes.

showError / errorboolean / ReactNode

showError: render the built-in validation error under the input after blur (red border, role="alert", aria-invalid); error: an explicit override (e.g. a "required" message). Added in v0.2.0.

messages / t / classNamesi18n & style overrides

Override copy with a messages object or t(); target individual parts (root / select / input / error…) with classNames.

Put a correct international phone input in your React app

Free, open source, TypeScript, and antd-free. Run npm i react-intl-phone-number now.

React Intl Phone Number — Drop-in International Phone Input for React | Mark Ku's Tech Blog - Mark Ku's Tech Notes