Available on Maven Central

Country selection
that feels native.

A polished country calling code picker for Compose Multiplatform with fast search, recent selections, format as you type, and local phone validation.

implementation("io.github.tharukack:countrycodekit:1.1.0")
  • Android
  • iOS
  • Offline first
CountryCodeKit picker shown as an opened bottom sheet

271 countriesReviewed bundled flags

Instant searchName, ISO, or code

3 presentationsSheet, dialog, full screen

Local validationGoogle metadata

See it in motion

One picker. Every essential flow.

Presentation, your way

Three native presentation modes.

CountryCodeKit picker using the bottom sheet presentation

Bottom sheet

Compact and native.

CountryCodeKit picker using the dialog presentation

Dialog

Focused and centered.

CountryCodeKit picker using the full screen presentation

Full screen

Maximum browsing space.

Customize it your way.

Match the picker to your product.

ColorsShapesTypographyFlagsFiltersBehavior

Format as you type

Country aware formatting.

Show familiar local spacing while keeping a clean phone number value.

Flag of Australia +61412 345 678

Google metadata

Validate locally, with confidence.

Get possible and valid checks, E.164 output, international formatting, and automatic detection without network requests.

Valid phone number+61412345678 ยท Australia

Installation

Add it to shared Compose UI.

build.gradle.kts
kotlin {
    sourceSets {
        commonMain.dependencies {
            implementation("io.github.tharukack:countrycodekit:1.1.0")
        }
    }
}

Quick start

Useful defaults in two calls.

  • Default bottom sheet
  • 271 countries
  • Persistent recents
  • Material styling
CountryPicker.kt
val pickerState = rememberCountryCodePickerState()

CountryCodePicker(
    state = pickerState,
)

val country = pickerState.selectedCountry
Text(country.formattedCallingCode)

API guide

Everything you need.

01

Core picker

val state = rememberCountryCodePickerState(
    initialCountry = CountryCodeCatalog.findByIsoCode("AU")!!,
    initialRecentSelections = listOf("NZ", "US"),
)

CountryCodePicker(state = state)

val selected = state.selectedCountry
CountryCodePickerstate, modifier, config, enabled, flagContent
CountryCodePickerStateselectedCountry, isOpen, query, recentSelections
State actionsopen(), dismiss(), updateQuery(), select()
02

Configuration

val config = CountryCodePickerConfig(
    style = CountryCodePickerStyle.Dialog,
    countryFilter = CountryCodePickerCountryFilter.Supported(
        listOf("AU", "NZ", "US")
    ),
    trigger = CountryCodePickerTriggerConfig(...),
    countryList = CountryCodePickerCountryListConfig(...),
)
stylecountryFiltertriggercountryListbottomSheetdialogfullScreen

Filters: All, Supported(isoCodes), or Unsupported(isoCodes).

03

Presentations

BottomSheetheightFractiongesturesEnabledshapeshowDragHandleborderWidthtonalElevationminWidth / maxWidth
DialogheightshapeborderWidthtonalElevationshadowElevationminWidth / maxWidthdismiss options
FullScreencontentMinWidthcontentMaxWidthuseStatusBarPaddinguseNavigationBarPaddingdismissOnBackPress
04

Country list

CountryCodePickerCountryListConfig(
    showSearch = true,
    showCallingCode = true,
    showRecentSelections = true,
    recentSelectionLimit = 3,
    separateCountriesByLetter = true,
    autoFocusSearch = false,
    flagStyle = CountryCodeFlagStyle.Rounded,
)
stringsTitle, search placeholder, section labels, empty state, accessibility labels.
searchShape, height, padding, icon sizes, clear button.
selectionRow and recent card shapes, borders, spacing, padding, indicators.
textStylesTitle, search, sections, country name, calling code, empty state.
colorsAccent, surfaces, content, selection, divider, border, scrim.
05

Trigger & flags

CountryCodePickerTriggerConfig(
    triggerElements = setOf(
        CountryCodePickerTriggerElement.Flag,
        CountryCodePickerTriggerElement.CountryCode,
        CountryCodePickerTriggerElement.Chevron,
    ),
    flagStyle = CountryCodeFlagStyle.Circle,
    shape = RoundedCornerShape(14.dp),
    borderWidth = 1.dp,
)
Trigger configElements, flag style, shape, border, text style, chevron, padding, spacing, colors.
Flag stylesRounded or Circle.
flagContentComposable slot that replaces bundled flags.
CountryCodeFlagStandalone bundled flag composable.
06

Phone state

val phone = rememberCountryCodePhoneState(
    initialCountry = CountryCodeCatalog.findByIsoCode("AU")!!,
    formatAsYouType = true,
    processing = CountryCodePhoneProcessing.ValidateAndDetectCountry,
)

phone.updateNumber(input)
CountryCodePicker(phone.pickerState, config = phone.pickerConfig)
InputsinitialCountry, initialNumber, formatAsYouType, processing, validationPreset, pickerConfig, initialRecentSelections
OutputsrawNumber, selectedCountry, validation, isValid, e164, international
ProcessingNone, Validate, DetectCountry, ValidateAndDetectCountry
07

Formatting

val formatted = CountryCodePhoneFormatter.format(
    number = "0412345678",
    country = state.selectedCountry,
    format = CountryCodePhoneFormat.International,
)

val live = CountryCodePhoneFormatter.formatAsYouType(
    number = "0412345678",
    country = state.selectedCountry,
)
NationalInternationalE164Rfc3966normalizeInput()format()formatAsYouType()
08

Validation

val result = CountryCodePhoneValidator.validate(
    number = phoneNumber,
    country = state.selectedCountry,
    preset = CountryCodePhoneValidationPreset.PhoneNumber,
)

if (result.isValid) submit(result.e164)
PhoneNumberFull country aware validation.
PossibleLengthPossible length for the selected country.
DigitsOnlyASCII digits only.
DigitsAndPossibleLengthDigits plus possible country length.
CustomLength(range, digitsOnly)Application defined length rule.
09

Catalog & results

CountryCodeisoCodenamecallingCodeformattedCallingCode
CountryCodeCatalogcountriesfindByIsoCode()search()hasBundledFlag()
CountryCodePhoneResultstatusisValide164internationalnormalizedDigitsdetectedCountry
Result statusEMPTYINVALID_REGIONNOT_A_NUMBERNON_DIGIT_CHARACTERSTOO_SHORT / TOO_LONGIMPOSSIBLE / INVALID / VALID

Built for shared UI

One Compose API. Two native targets.

AndroidCompose Multiplatform
iOSCompose Multiplatform
OfflineNo runtime phone service
MITOpen source

Ready to ship?

Make country selection feel like part of your app.

View on GitHub Install 1.1.0