Skip to main content
CountrySelect combines a labeled trigger, decorative flags, country search, selected options, and an explicit no-country choice. It uses the shared Dropdown picker behavior. Your application supplies country data and translated text and decides how selected values are stored.

Prepared choices

Each choice has a unique, non-empty value, a display label, and an optional flag. Values are opaque strings. They can be country names, identifiers, or codes according to your application’s existing storage format. Selecting a choice reports its value unchanged.
flag accepts a React node and is decorative. The country label supplies the accessible option name. Country lists, flag assets, locale selection, and translations remain in the host application.

Empty and unknown values

The empty string ('') represents no country. The no-country option appears beside the supplied choices and reports that empty string when selected. Reserve it for the empty selection instead of using it as a country value. An unknown value displays noCountryLabel and the no-country icon. It does not call onValueChange or overwrite the host value. This lets the application decide how to handle a stored value that is absent from the current choices.

Search and interaction

Search matches the prepared display labels. It ignores letter case, optional accents in Latin, Greek, Arabic, and Hebrew text, and Cyrillic stress marks, treats the Cyrillic ё as е, and folds letters such as ø, æ, and ß into o, ae, and ss. It also ignores standalone accent characters such as ^, `, ´, ¨, and ˇ, so a pending dead key does not hide matches. Marks that form distinct letters remain significant, such as Japanese voicing marks, Indic vowel signs, and the Cyrillic й. A partly typed Korean syllable, such as ㅎ or 하, matches syllables that start with it, such as 한. noCountryLabel participates in the same search. While a search is active, matching countries are listed before the no-country choice, so Enter picks the first matching country. When only the no-country choice matches, Enter selects it. A query with no matching options displays noResultsLabel. Closing and reopening the picker clears its search. The picker handles pointer selection, keyboard movement, selected-option presentation, focus, and closing. Selecting an option closes the popup. Escape closes it and restores trigger focus. Each instance has independent popup and search state. Provide a visible label, or use aria-label or aria-labelledby on the trigger. aria-labelledby takes precedence over a non-empty aria-label, which takes precedence over the visible label, and the popup takes the same name as the trigger. The visible label also names a trigger that render replaces with a non-button element. When the trigger is named this way, the selected country is its accessible description. Without any of them, the selected country names the trigger and the popup. A tooltip reveals the full selected label when it is truncated. searchLabel supplies the search input’s placeholder and accessible name, noCountryLabel the no-country text, and noResultsLabel the empty-result text. They default to Search, No country, and No results. Pass translated strings when your application is localized. Native trigger attributes, event handlers, className, style, and ref apply to its button. disabled prevents opening and selection. A picker with no supplied countries is disabled as well. If either condition occurs while the popup is open, the popup closes, reports onOpenChange(false), and returns focus to the trigger. Enabling the picker again does not reopen it automatically. While disabled, the trigger stays focusable, is marked with aria-disabled, and never opens. Like a native disabled button, it skips consumer onClick, onMouseDown, onPointerDown, onKeyDown, and onKeyUp handlers. Function forms of className, style, and render receive disabled: true in the trigger state.

Host integration

Use open and onOpenChange when the application needs to register or control the popup. Without open, the picker manages its own open state. popupProps accepts Dropdown popup options for positioning, portal placement, and focus handling. The popup takes its name from the trigger, so popupProps does not accept aria-label or aria-labelledby. Keep application dropdown IDs, focus stacks, field metadata, persistence, and editing lifecycle in the host adapter. Changing the display label or flag does not require changing the stored value.

Front component renderer

The React and Preact front component sandboxes render the selected country, decorative flag, and disabled trigger. Opening the popup is currently unsupported. Base UI reads pointer contact data from the nativeEvent of the forwarded event, which the sandbox does not provide. When the popup content still mounts, the Dropdown reads the popup element’s dataset, which worker elements do not provide. Search, selection, popup focus, and closing are therefore unavailable in those sandboxes for now. Renderer fixtures check the initial presentation and the disabled trigger, then assert the known opening errors. The UI Storybook exercises these interactions in a regular browser.

Props

string | ((state: PopoverTriggerState) => string | undefined)
Class applied to the trigger.
readonly CountryChoice[]
required
Prepared country choices with unique non-empty values, display labels, and optional decorative flags.
boolean
default:"false"
Prevents opening and selection while the trigger stays focusable. An empty country list is also disabled.
string
ID of the trigger. Generated when omitted.
string
Optional visible label that names the trigger and the popup.
boolean
default:"true"
Whether the component renders a native <button> element when replacing it via the render prop. Set to false if the rendered element is not a button (e.g. <div>).
string
default:"No country"
Text of the no-country choice, also displayed when no country is selected.
string
default:"No results"
Text displayed when no choice matches the search.
((open: boolean) => void)
Reports popup opening and closing.
(value: string) => void
required
Reports the selected choice value, or an empty string when no country is selected.
boolean
Controls whether the country popup is open.
Omit<DropdownContentProps, "children" | "aria-label" | "aria-labelledby" | "keepMounted">
Dropdown popup positioning, portal, focus, and event options for host integration.
Ref<HTMLButtonElement>
Ref to the trigger element.
ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, PopoverTriggerState>
Replaces the trigger element while preserving its behavior and props.
string
default:"Search"
Placeholder and accessible name of the search input.
CSSProperties | ((state: PopoverTriggerState) => CSSProperties | undefined)
Style applied to the element, or a function that returns a style object based on the component’s state.
string
required
Selected choice value. An empty string selects no country.