PhoneInput

Molecule
A phone number field: the Input's box with a country segment at its start (the chosen country and a caret, which open a list of countries with their names and dial codes) and that country's dial code inline before the number. On the web the segment is a small chip inside the field naming the country by its ISO code, and the dial code and the number are set in the mono face, and in the country list each row is a 16px flag 10px from the name with the dial code a 12px mono note at its end; on iOS and Android it is the country's flag.

Playground

Every control sets a real prop of PhoneInputProps. The JSX below updates as you go.
Phone
+1
Props
label
string
country
one of
value
string
Size
pick one
required
boolean
error
boolean
disabled
boolean
JSX · PhoneInputProps
<PhoneInput label="Phone" country="US" value="415 555 0132" />

Variants

8 examples from src/molecules/phone-input/phone-input.md, each rendered live from its own JSX.
Phone number
+1
Pre-filled
<PhoneInput label="Phone number" defaultCountry="US" defaultValue="(415) 728-3046" />
Phone number
+44
Another country
<PhoneInput label="Phone number" defaultCountry="GB" placeholder="Add your phone number" />
Phone number
+1
Error
<Field label="Phone number" error="Invalid phone number.">
<PhoneInput defaultCountry="US" defaultValue="(415) 72" />
</Field>
Phone number
+1
Required
<PhoneInput label="Phone number" required placeholder="Add your phone number" />
Phone number
+1
Selected: CA
Controlled country
<Stateful initial="CA">
{(country, setCountry) => (
<Column snug>
<PhoneInput label="Phone number" country={country} onCountryChange={setCountry} placeholder="Add your phone number" />
<Typography small muted>Selected: {country}</Typography>
</Column>
)}
</Stateful>
Phone number
+49
Custom country list
<PhoneInput
label="Phone number"
countries={[
{ code: "FR", name: "France", dialCode: "+33" },
{ code: "DE", name: "Germany", dialCode: "+49" },
{ code: "ES", name: "Spain", dialCode: "+34" },
]}
defaultCountry="DE"
placeholder="Add your phone number"
/>
Phone number
+1
Disabled
<PhoneInput label="Phone number" disabled defaultValue="(415) 728-3046" />
Small
+1
Default
+1
Large
+1
Sizes
<Column relaxed>
<PhoneInput small label="Small" placeholder="Add your phone number" />
<PhoneInput label="Default" placeholder="Add your phone number" />
<PhoneInput large label="Large" placeholder="Add your phone number" />
</Column>

Sizes

Phone
+1
small
Phone
+1
default
Phone
+1
large

States

Hover, focus and press are pinned so they can be compared side by side; the rest are real props.
Phone
+1
default
Phone
+1
focus
Phone
+1
error
Phone
+1
disabled

Anatomy

Phone
+1
1
Label
2
Country trigger
3
Dial code
4
Number
5
Error
Dimmed parts appear only in some states or variants.

Props

28 props on PhoneInputProps, grouped as they are declared in source. Required props are marked *.
Prop
Type
Default
Description
Props
19 props
value
string
–
The national number typed so far (controlled). Omit and use defaultValue for uncontrolled use.
onChangeText
(text: string) => void
–
Called with the new number on each keystroke.
countries
readonly PhoneCountry[]
–
The countries the segment offers, in the order shown. Defaults to the kit's curated PHONE_COUNTRIES list; pass a full, localized, or reordered list.
country
string
–
The selected country's ISO alpha-2 code (controlled). Omit and use defaultCountry.
defaultCountry
string
–
Initial country code for uncontrolled use. Defaults to "US" when the list has it, else the first row.
onCountryChange
(code: string) => void
–
Called with the chosen country's code when a row is picked (both modes).
placeholder
string
–
Placeholder shown while the number is empty.
label
string
–
The field's persistent label, rendered above the box on every platform (a grouped field never floats its label). It is the number field's programmatic name, and Field delegates its label into it.
required
boolean
false
Marks the field as required: a destructive "*" after the label (decorative, never in the accessible name), and the number field announced as required, through aria-required on the web and with the word in its name ("Phone number, required") on iOS and Android.
autoFocus
boolean
false
If true, focuses the input on componentDidMount. The default value is false.
defaultValue
string
–
Provides an initial value that will change when the user starts typing. Useful for simple use-cases where you don't want to deal with listening to events and updating the value prop to keep the controlled state in sync.
maxLength
number
–
Limits the maximum number of characters that can be entered. Use this instead of implementing the logic in JS to avoid flicker.
onBlur
((e: BlurEvent) => void)
–
Callback that is called when the text input is blurred Note: If you are trying to find the last value of TextInput, you can use the onEndEditing event, which is fired upon completion of editing.
onFocus
((e: FocusEvent) => void)
–
Callback that is called when the text input is focused
onSubmitEditing
((e: TextInputSubmitEditingEvent) => void)
–
Callback that is called when the text input's submit button is pressed.
onKeyPress
((e: TextInputKeyPressEvent) => void)
–
Callback that is called when a key is pressed. This will be called with { nativeEvent: { key: keyValue } } where keyValue is 'Enter' or 'Backspace' for respective keys and the typed-in character otherwise including ' ' for space. Fires before onChange callbacks. Note: on Android only the inputs from soft keyboard are handled, not the hardware keyboard inputs.
returnKeyType
ReturnKeyTypeOptions
–
enum('default', 'go', 'google', 'join', 'next', 'route', 'search', 'send', 'yahoo', 'done', 'emergency-call') Determines how the return key should look.
testID
string
–
Used to locate this view in end-to-end tests
ref
React.Ref<RNTextInput>
–
Ref to the underlying React Native host. Supports object refs and callback refs; native methods follow the platform's behavior.
State
4 props
error
boolean
false
invalid
boolean
false
disabled
boolean
false
readOnly
boolean
false
Read-only: shows the number but blocks editing and the country list.
Size
pick one
5 props
small
boolean
false
large
boolean
false
accessibilityLabel
string
–
Accessible name for the number field when there is no label.
aria-describedby
string
–
ID of the helper/error text that describes the field (its nativeID).
style
LayoutStyle
–
Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.
MeasureProps · width steps xxxs 192 · xxs 256 · xs 320 · sm 384 · md 448 · lg 512 · xl 576 · xxl 672 · xxxl 768 · wide 896 · wider 1024 · widest 1152 · page 1280, plus start to pin to the leading edge.

Accessibility and keyboard

Keyboard
ArrowDown
Opens the list
ArrowUp
ArrowDown
Moves through options
Enter
Commits the active option
Escape
Closes the list, keeps the text
Semantics
Roles
button
option
States
disabled
expanded
selected
ARIA on web
aria-controls
aria-describedby
aria-expanded
aria-haspopup
aria-invalid
aria-label
aria-labelledby
aria-required
aria-selected
Below the platform minimum, the touch area grows to 44 pt on iOS and 48 dp on Android without moving the layout.
From the docs
The number and the country are each controlled (value / country) or self-managed (defaultValue / defaultCountry), the segment defaults to the kit's curated PHONE_COUNTRIES list (pass countries for a full or localized one), and the number field asks for the phone keypad. Pass label (and required) to name it; error paints the whole box, segment included, and Field delegates its label, required mark and error into it. The required star is decorative: a screen reader hears the number field as required
In glass mode the country list is a dense-layer glass card under the box; the box, its segment and its number stay in place. A pick commits the country and returns focus to the number at once, and a field that becomes disabled or read-only while the list is open closes it. Solid mode paints the skin's own list.

Platform skins

The playground's props on each platform: same tree, native shapes, type and touch sizes.
Phone number
+44
Web
control 10 · field 10 · card 16 · Instrument Sans
Phone number
+44
iOS
capsule controls · field 8 · card 12 · SF Pro · 44 pt
Phone number
+44
Android
Material 3 stadium · field 4 · card 12 · Roboto · 48 dp

Usage

<PhoneInput label="Phone number" placeholder="Add your phone number" />
The number and the country are each controlled (value / country) or self-managed (defaultValue / defaultCountry), the segment defaults to the kit's curated PHONE_COUNTRIES list (pass countries for a full or localized one), and the number field asks for the phone keypad. Pass label (and required) to name it; error paints the whole box, segment included, and Field delegates its label, required mark and error into it. The required star is decorative: a screen reader hears the number field as required, from aria-required on the web and from its name ("Phone number, required") on iOS and Android. On iOS the field is drawn to the iOS input-field reference: the white box, the flag and gray caret segment with its state-coloured divider, the dial code in the placeholder gray.
In glass mode the country list is a dense-layer glass card under the box; the box, its segment and its number stay in place. A pick commits the country and returns focus to the number at once, and a field that becomes disabled or read-only while the list is open closes it. Solid mode paints the skin's own list.

Tokens

Read from the playground render. Values follow the scheme and the ion hue.
--bg2
--fd
--fm
--ft
--ln2
--sf3
--tx2
--tx3

Related components