Skip to content

Country Code Picker

JitPack License: MIT API 24+ Platforms: Android | iOS

A lightweight, fully customizable Compose Multiplatform library for Android and iOS: country selection, country-code selection, phone number validation, and real-time formatting based on country-specific rules — written once in common code.

Everything is plain Compose state: no ViewModels, no navigation coupling, and every component is a controlled component whose value you own.

  • Country picker


    Searchable list of 236 countries and territories with flags and dial codes. Full, compact, flag-only and dial-code selector variants, region filters, recents and suggestions.

    Country selector

  • Single and multi-selection


    One country, or several with Cancel / Reset / Confirm. The confirmed selection changes only when the user taps Confirm.

    Multi-selection

  • Phone number field


    Country prefix and number editor in one outlined field. Progressive as-you-type formatting and E.164 output from Google libphonenumber, never from string concatenation.

    Phone number field

  • Validation and verification


    Granular validity that tells still typing apart from wrong, plus an optional, decoupled OTP verification flow backed by your own SMS or Firebase provider.

    Validation · Verification

  • Country detection


    SIM → network → locale, with no location permission. Detection is a suggestion and never overrides a country the user chose.

    Country detection

  • Themeable and accessible


    Colors, shapes, dimensions, typography and motion all flow from CountryPickerDefaults and follow your Material 3 theme. 48dp touch targets, screen-reader friendly, no color-only signalling.

    Theming · Accessibility

Two layers, one foundation

  • Country Picker (com.ezzy.ccp.countrypicker) is the general-purpose foundation: selectors, the bottom sheet, search, configuration, theming, detection, phone formatting and verification. This is the API to build on.
  • PhoneNumberInput (com.ezzy.ccp.components) is the original phone-number component. It runs on the Country Picker foundation internally, so existing call sites keep working unchanged. See the legacy API and the migration guide.

Install

Add the dependency from Maven Central — to commonMain in a Kotlin Multiplatform module, or to dependencies in an Android-only one. Nothing else is needed on iOS. Full details in Getting started.

build.gradle.kts
kotlin {
    sourceSets {
        commonMain.dependencies {
            implementation("io.github.ezekielwachira:ccp:<LATEST_VERSION>")
        }
    }
}

A first look

var country by rememberSaveable { mutableStateOf<Country?>(null) }

CountrySelector(
    selectedCountry = country,
    onCountrySelected = { country = it },
    label = UiText.of("Country of residence"),
)

val phoneState = rememberPhoneNumberFieldState(
    initialCountry = DefaultCountryDataSource.findByIso2("KE")!!,
)

PhoneNumberField(
    state = phoneState,
    onValueChange = { value ->
        value.e164Number   // "+254712345678", or null while unparseable
        value.isValid      // true only for a real, dialable number
    },
)

Demo

A short recording of the sample app is on the repository README. The sample screen that reproduces the flow lives in YourDetailsSampleScreen.kt, and every state described in these docs has a matching @Preview in CountryPickerPreviews.kt.

License

Released under the MIT License. Copyright © 2025 Ezekiel Wachira.