Every Country, With Flags
A country selector with SVG flags and dial codes, in the language of the visitor's browser, or in a locale you pin yourself.
NWD Phone Input (Global & Flags) was built to replace Bubble’s native phone input and offers far more styling flexibility and control. It brings a searchable country selector, formatting as you type, and per-country validation together in one polished component, returning numbers in the international E.164 format and split into their country, area and local parts. Fully customizable through 50+ properties, giving you complete control over every visual and behavioral detail.
Built for what Bubble does not cover.
Bubble's native phone field is not a dedicated input. It is one type of a generic input that also does text, number, password, email and others. It accepts a phone number and can check a basic format, but it has no country selector, no flags, no formatting while the person types, and no way to tell a valid São Paulo mobile from eleven digits that merely look like one. Whatever is typed is what your database gets, in whatever shape the person chose to type it.
A country selector with SVG flags and dial codes, in the language of the visitor's browser, or in a locale you pin yourself.
Find a country by name, by ISO code or by dial code, with your own message when nothing matches.
A number is checked against the rules of the country it belongs to, not against a generic pattern.
E.164 for your database, the national form for your screens, and the country, area and local parts on their own.
The field, the selector, the floating panel, its search box and each country row are all yours to style.
Fully operable from the keyboard and announced to screen readers, with motion preferences respected.
In detail
Place the plugin element wherever you need it.
Adjust the settings to match your use case, including the default country, the allowed and preferred countries, and the validation.
Use the value changed and country changed events to capture the confirmed number and read the exposed states to use them anywhere in your app.
The number is published in several shapes at once, and they are not interchangeable. Store value, which is E.164 and unambiguous anywhere in the world; show value (formatted), which is how the number is written inside its own country. area code and local number exist for forms that keep the parts in separate columns.
Text displayed in the input while it has no value.
Color of the placeholder text.
Color of the line between the country selector and the input. Leave it empty to follow the element's native border color, or a light grey when the element has no border.
How the number is formatted inside the input.
This changes only what the person sees while typing. The `value` state is always E.164, whichever format you pick here, so your database is not affected by this choice.
Checks whether the number is valid for the selected country.
BCP 47 locale that defines the language of the country names (for example en-US or pt-BR). When empty or invalid, uses the browser locale.
Shows the country flag in the selector.
Shows the dial code (+55) next to the flag.
ISO codes available in the selector. Leave empty to list all countries. One code per line, and it accepts a dynamic list, so the countries can come from your data.
One ISO code per line, pressing Enter between them. A default value whose country is not on this list is ignored, and the field opens on the default country instead.
ISO codes removed from the selector. A blocked country is removed even when it is listed as allowed. Leave empty to block none. One code per line, and it accepts a dynamic list, so the countries can come from your data.
ISO codes shown at the top of the list. One code per line, and it accepts a dynamic list, so the countries can come from your data.
ISO 3166 code of the country selected on load (US, BR, PT...).
Phone number applied on load and on reset, in international format (+5511912345678).
Sets the maximum number of visible countries before scrolling. Accepts values between 1 and 30.
The height is worked out from this count and the font size you set, so the panel shows this many countries whatever the typography. The rest scrolls.
Preferred or forced opening direction of the floating panel relative to the input.
Opening animation of the floating panel.
Background color of the floating panel.
Sets the border color of the floating panel.
Intensity of the glassmorphism effect on the floating panel.
Look of the scrollbar in the panel lists: hidden (the list still scrolls), minimal (a handle only) or arrows (a handle with an arrow at each end), each in thin or regular width. Firefox shows its own scrollbar for arrows.
Fades the top and bottom edges of the panel lists while there are more items to scroll to on that side.
Message displayed inside the panel when there are no options to show.
Font color of the empty state message.
Shows a search input in the country list.
The search matches a country by name in the visitor's language, by ISO code, and by dial code, so typing `br`, `BR` or `+55` all find Brazil.
Placeholder of the country search input.
Text read by screen readers after each country search. {count} is replaced with the number of countries found.
Height of the search field, in pixels. Leave it empty to follow the element's height.
Sets the background color of the search input.
Sets the border color of the search input.
Sets the border color of the search input when focused.
Sets the color of the text typed in the search input. It is optional, if not set falls back to the native font color set in the main input.
Optional. Left empty, the text typed in the search follows the font color of the main input, so the panel matches the field without a second setting.
Sets the font color of the search input placeholder.
Enables automatic clearing of the search text when the panel closes. Disabled keeps the typed search for the next time the panel opens.
Displays the search icon inside the search input.
Sets the icon displayed next to the search input.
Sets the color of the search icon.
Sets the icon used to clear the search input. It appears only while there is text typed.
Sets the color of the clear icon.
Sets the background color of countries in their default state. Empty leaves them transparent.
Optional, and empty on purpose: the list is a column of flags, and a background behind every row competes with them. Set it only if you want the rows banded.
Sets the border color of countries in their default state. Empty leaves them without a visible border.
Sets the font color of countries in their default state. Empty follows the element font color.
Country background color on hover.
Sets the border color of countries when hovered.
Country font color on hover. Empty keeps the element font color.
Country background color when selected.
Sets the border color of countries when selected.
Font color of the selected country.
Disables the component, preventing any interaction.
Input background color when disabled.
Input border color when disabled.
Input font color when disabled.
Marks the field as required and enables input validation.
Input background color when invalid.
Input border color when invalid.
Input background color when focused.
Input border color when focused.
Name read by screen readers. When empty, uses the placeholder or the visible label.
Hint read by screen readers after the name. Empty for none.
Values the element exposes for the rest of the page to read.
An optional input can still be invalid: once there is a number, it has to be valid for the selected country, unless Validate number? is unchecked.
Number in international E.164 format (+5511912345678). Empty when the input is empty.
Number grouped the way it is written in the selected country ((11) 91234-5678). Empty when the input is empty.
ISO code of the selected country.
Dial code of the selected country (+55).
Area code of the number, in the countries that use one (the DDD in Brazil). Empty where the country has no area code, such as Germany, France and Spain.
Number without the dial code and without the area code. Where the country has no area code, it is the whole national number.
The locale that actually applied: the Locale field when it is valid, or the visitor's browser language when the field is empty or its form is not recognised.
True when the component is not disabled.
True when the input is marked as required.
True when the value is accepted. False when it is required and empty, or Validate number? is checked and the number is not valid for the selected country. It updates on every change, so a workflow can rely on it; the invalid style only shows after the person leaves the field or closes the panel, or when a workflow sets the value.
True while the input has focus.
Where a workflow can start.
Triggered when the number is confirmed with a different value: leaving the input, pressing Enter, changing the country or resetting.
Triggered when a different country is selected.
What a workflow can tell the element to do.
Restores the default number and country, or clears the input.
Focuses the phone input.
Writes a phone number into the field from a workflow. A number starting with + carries its own country; without it, the number is read in the default country.
Yes applies the value even while the element is disabled. No makes the action do nothing in that state.
The value to write into the field. It goes through the same treatment as a value typed by the user. An empty value clears the field, keeping the selected country.
Six separate states. `value` is the number in international E.164 format (`+5543991234567`), which is what belongs in your database and what an SMS gateway expects. `value (formatted)` is the same number grouped the way it is written inside the country (`(43) 99123-4567`). `country code` is the ISO code (`BR`), `dial code` is `+55`, `area code` is the DDD (`43`) and `local number` is what is left (`991234567`).
Because those countries do not have one. Brazil, the United States, Canada, Chile and Russia use an area code; Germany, France, Spain and the United Kingdom do not, and the digits that look like one there are a mobile or carrier prefix. The plugin publishes an area code only where the country really has one, and leaves the state empty everywhere else, rather than handing you a number that looks like a region and is not.
It validates against the rules of the selected country, using libphonenumber, the same library behind Google's phone number handling. A mobile number with the wrong number of digits for its area fails even though it looks plausible. You can turn validation off with Validate number? if you only want formatting.
Yes. Allowed countries restricts the list to the ISO codes you list, one per line. Blocked countries removes the ones you list and keeps the rest. Preferred countries pins the ones you list to the top, above a divider, without removing the rest. Leave all three empty and every country is offered.
The selector follows it. Pasting a number that starts with `+` switches the country to the one the number belongs to, as long as that country is allowed, and the digits are reformatted for it. The same applies to the Set value action.
From libphonenumber-js, pinned to one version and loaded once per page from a CDN, around 60 KB compressed. Flags are SVG files fetched one at a time, only as they appear on screen. Until the library arrives the field still accepts digits, simply without formatting, so nothing blocks typing.
Yes. The Set value action writes a number from anywhere in your app, with control over whether it applies while the input is disabled; Reset returns the field to its default value and country; and Focus puts the cursor in it. Two events let you react: one when the number changes and one when the country changes.
This plugin is maintained by GCS Studios and is part of the NWD UI - Input family, form controls built from scratch for Bubble, inspired by a personal component library originally built for React. Each one is carefully designed and tested in real applications before release, for the level of control, polish and reliability that native Bubble inputs often do not provide. See more plugins on the GCS Studios contributor page.
Each control here is drawn by the plugin instead of being restyled from a native one, so they match each other across the library and keep the same shape in every browser.