VisorVisor
ComponentsForm

Phone Input

An international phone number input with country code selection, geo-IP detection, format-as-you-type, and validation.

Default

With onChange

Sizes

Disabled

Installation

npx visor add phone-input

This copies three files into your project:

  • components/ui/phone-input/phone-input.tsx — the component
  • components/ui/phone-input/phone-input.css — global theme overrides for intl-tel-input
  • components/ui/phone-input/phone-input.module.css — wrapper styles

It also installs intl-tel-input as a dependency.

Important: Import the global CSS file in your app layout or entry point:

import '@/components/ui/phone-input/phone-input.css';

Usage

import { PhoneInput } from '@/components/ui/phone-input/phone-input';

function MyForm() {
  const [phone, setPhone] = useState('');
  const [isValid, setIsValid] = useState(false);

  return (
    <PhoneInput
      name="phone"
      onChange={(value, valid) => {
        setPhone(value);
        setIsValid(valid);
      }}
    />
  );
}

API Reference

PhoneInputProps

PropTypeDefaultDescription
idstringHTML id attribute for the input element.
namestringHTML name attribute for the input element.
valuestringInitial phone number value (e.g. "+14155551234").
placeholderstringPlaceholder text for the input.
requiredbooleanfalseWhether the field is required.
disabledbooleanfalseWhether the field is disabled.
classNamestringAdditional CSS classes applied to the wrapper.
onChange(value: string, isValid: boolean) => voidCalled with the full international number and validation status on every change.
onBlur() => voidCalled when the input loses focus.

Features

  • Country code selection — searchable dropdown with all countries and dial codes
  • Geo-IP detection — auto-detects user's country on mount with US fallback
  • Format-as-you-type — applies per-country formatting rules as users type
  • Validation — powered by libphonenumber, returns validation status via onChange
  • SSR-safe — renders a basic <input type="tel"> during server render, hydrates with full functionality on mount

CSS Import

The component requires a global CSS import for the intl-tel-input dropdown theming. This file overrides the library's default styles with Visor design tokens:

// In your layout.tsx or _app.tsx
import '@/components/ui/phone-input/phone-input.css';

The CSS is global (not a CSS Module) because intl-tel-input renders its dropdown via document.body, outside React's component tree.

Accessibility

  • Renders a native <input> with type="tel" and autocomplete="tel" for appropriate mobile keyboard and autofill
  • Always pair with a <Label> using htmlFor/id, or provide aria-label directly
  • The country dropdown supports keyboard navigation and search
  • Focus is maintained during parent re-renders (callback refs pattern)