ComponentsInputs
Phone Input
International phone number input with country selector, flag emojis, and dial code search. Supports 50 countries with built-in formatting and validation.
Installation
bash npx shadcn@latest add @elements/phone-input Usage
import { PhoneInput } from "@/components/ui/phone-input";<PhoneInput
defaultCountry="US"
placeholder="Enter phone number"
onValueChange={(value, country) => {
console.log(value, country.dialCode);
}}
/>Props
| Prop | Type | Required | Description |
|---|---|---|---|
value | string | No | Phone number — pass this to control the component |
defaultValue | string | No | Initial phone number when uncontrolled |
onValueChange | (phone: string, country: Country) => void | No | Callback when phone number or country changes |
defaultCountry | string | No | Default country code (ISO 3166-1 alpha-2, e.g. "US", "GB", "IN") |
placeholder | string | No | Placeholder text |
disabled | boolean | No | Disable the input |
showFlags | boolean | No | Show country flag next to dial code (default: true) |
label | string | No | Accessible label for the input |
className | string | No | Additional CSS classes |
Any other prop — name, required, autoComplete, data-* — is spread onto the
underlying <input>, and the ref is forwarded to it, so the component works inside
a plain HTML form.
Country Object
| Property | Type | Description |
|---|---|---|
code | string | ISO 3166-1 alpha-2 code (e.g. "US", "GB", "IN") |
dialCode | string | Dial code (e.g. "+1", "+44", "+91") |
name | string | Country name |
flag | string | Flag emoji |
Examples
With Babelize SDK
Pair Phone Input with the Babelize SDK for locale-aware validation:
"use client";
import { useState } from "react";
import { PhoneInput } from "@/components/ui/phone-input";
import { useBabelize } from "@babelize/sdk/react";
export function ContactPhone() {
const { locale } = useBabelize();
const [phone, setPhone] = useState("");
return (
<PhoneInput
value={phone}
onValueChange={(value, country) => {
setPhone(value);
// Validate against locale-specific rules
}}
defaultCountry={locale === "en" ? "US" : locale === "de" ? "DE" : "GB"}
placeholder="Enter phone number"
/>
);
}With Form Validation
"use client";
import { useState } from "react";
import { PhoneInput } from "@/components/ui/phone-input";
export default function CheckoutForm() {
const [phone, setPhone] = useState("");
const [error, setError] = useState("");
const validate = (value: string) => {
if (value.length < 10) {
setError("Phone number is too short");
} else {
setError("");
}
};
return (
<div>
<PhoneInput
value={phone}
onValueChange={(value) => {
setPhone(value);
validate(value);
}}
defaultCountry="US"
placeholder="Enter phone number"
/>
{error && <p className="text-red-500 text-sm mt-1">{error}</p>}
</div>
);
}With Country Filter
"use client";
import { PhoneInput } from "@/components/ui/phone-input";
const COUNTRIES = [
{ code: "US", dialCode: "+1", name: "United States", flag: "🇺🇸" },
{ code: "GB", dialCode: "+44", name: "United Kingdom", flag: "🇬🇧" },
{ code: "CA", dialCode: "+1", name: "Canada", flag: "🇨🇦" },
{ code: "AU", dialCode: "+61", name: "Australia", flag: "🇦🇺" },
];
export default function App() {
return (
<PhoneInput
defaultCountry="US"
onValueChange={(phone, country) => console.log(phone, country)}
/>
);
}Features
- 50 countries — pre-loaded with dial codes, flags, and names
- Dropdown search — filter countries by name or dial code
- Flag emojis — auto-detected from country code, with
showFlagstoggle - Keyboard accessible — arrow keys, Enter, Escape, Tab navigation
- ARIA labels — proper
aria-expanded,aria-haspopup,aria-label - Dark mode — built with Tailwind CSS, dark-mode compatible
- Controlled/uncontrolled — works with or without
valueprop
Supported Countries
The input ships with 50 countries pre-loaded. Use the dropdown search to find any country by name or dial code. The full list includes:
| Country | Code | Dial Code | Flag |
|---|---|---|---|
| United States | US | +1 | 🇺🇸 |
| United Kingdom | GB | +44 | 🇬🇧 |
| Canada | CA | +1 | 🇨🇦 |
| Australia | AU | +61 | 🇦🇺 |
| India | IN | +91 | 🇮🇳 |
| Germany | DE | +49 | 🇩🇪 |
| France | FR | +33 | 🇫🇷 |
| Japan | JP | +81 | 🇯🇵 |
| Brazil | BR | +55 | 🇧🇷 |
| South Korea | KR | +82 | 🇰🇷 |
| ...and 40 more via the dropdown search |
Dependencies
This component uses:
clsxandtailwind-merge(bundled as dependencies)
Peer dependencies:
react>= 18react-dom>= 18tailwindcss>= 3
Credits
Created by sapatmohit.