Skip to main content

Theming & Styles

Three levels of customization, from cheapest to most granular:

  1. theme — a ready-made light / dark palette
  2. phoneInputStyles / modalStyles — override any individual element
  3. customFlag / customCaret / modalCountryItemComponent — replace whole pieces of UI

Dark mode — theme

<PhoneInput theme="dark" />

theme accepts 'light' (default) or 'dark', and applies to both the input and the country selector modal.

Follow the OS setting with React Native's useColorScheme:

import {useColorScheme} from 'react-native';

const scheme = useColorScheme(); // 'light' | 'dark' | null

<PhoneInput theme={scheme === 'dark' ? 'dark' : 'light'} />;

theme is the base layer — anything you pass in phoneInputStyles or modalStyles wins over it, so you can start from dark and repaint only what you need.

Right-to-left — rtl

<PhoneInput rtl />

Swaps the flag/calling-code block to the right of the input, for Arabic, Hebrew, Persian and Urdu layouts. Pair it with the matching language:

import {I18nManager} from 'react-native';

<PhoneInput rtl={I18nManager.isRTL} language="ar" />;

Custom caret and flag

<PhoneInput
customCaret={() => <Icon name="chevron-down" size={20} color="#6b7280" />}
customFlag={(country) => <Image source={flags[country.cca2]} style={{width: 24}} />}
/>

customFlag also removes the need for the flag emoji font.

<PhoneInput
modalType="bottomSheet" // 'bottomSheet' | 'popup'
initialBottomsheetHeight="60%"
minBottomsheetHeight="40%"
maxBottomsheetHeight="90%"
isFullScreen={false}
/>

modalType defaults to 'popup' on Web and 'bottomSheet' on iOS/Android.

phoneInputStyles

Source: lib/interfaces/phoneInputStyles.ts

PropertyTypeDescription
containerViewStyleMain input container
flagContainerViewStyleFlag and dropdown container
flagTextStyleFlag emoji styling
caretTextStyleDropdown arrow
dividerViewStyleSeparator line
callingCodeTextStyleCountry calling code
inputTextStylePhone number input

modalStyles

Source: rn-country-select countrySelectStyles

PropertyTypeDescription
backdropViewStyleModal background overlay
containerViewStyleModal main container
contentViewStyleModal content area
dragHandleContainerViewStyleDrag handle area
dragHandleIndicatorViewStyleDrag handle indicator
searchContainerViewStyleSearch input wrapper
searchInputTextStyleSearch input field
listViewStyleCountries list container
countryItemViewStyleIndividual country row
flagTextStyleCountry flag in list
countryInfoViewStyleCountry details container
callingCodeTextStyleCalling code in list
countryNameTextStyleCountry name in list
sectionTitleTextStyleSection headers
closeButtonViewStyleClose button container
closeButtonTextTextStyleClose button text
countryNotFoundContainerViewStyleNo results container
countryNotFoundMessageTextStyleNo results message
alphabetContainerViewStyleAlphabet filter container
alphabetLetterViewStyleAlphabet letter item
alphabetLetterTextTextStyleAlphabet letter text
alphabetLetterActiveViewStyleActive letter state
alphabetLetterDisabledViewStyleDisabled letter state
alphabetLetterTextActiveTextStyleActive letter text
alphabetLetterTextDisabledTextStyleDisabled letter text

Example

<PhoneInput
phoneInputStyles={{
container: {backgroundColor: '#1f2937', borderRadius: 12},
input: {color: '#fff'},
callingCode: {color: '#fff'},
caret: {color: '#9ca3af'},
}}
modalStyles={{
backdrop: {backgroundColor: 'rgba(0,0,0,0.7)'},
content: {backgroundColor: '#111827'},
countryName: {color: '#fff'},
callingCode: {color: '#9ca3af'},
}}
/>

Styling the disabled state

disabled blocks the whole component; modalDisabled locks only the country. Neither applies a style of its own, so drive it from your own state:

const [isDisabled, setIsDisabled] = useState(true);

<PhoneInput
disabled={isDisabled}
phoneInputStyles={{
container: isDisabled ? {backgroundColor: '#e5e7eb', opacity: 0.7} : {},
}}
/>;

Placeholders and modal copy

<PhoneInput
placeholderType="number" // default: real example number per country
placeholder="Your phone number" // overrides placeholderType
modalSearchInputPlaceholder="Search country"
modalNotFoundCountryMessage="No country found"
modalPopularCountriesTitle="Popular"
modalAllCountriesTitle="All countries"
/>

Leave these out and they are translated automatically from the language prop.

Next