CurrencyPicker combines a compact currency trigger, searchable options, and a Dropdown. Supply a currency catalogue and use one component for ordinary selection. Compose Root, Trigger, and Options with Dropdown when the popup needs other content or pages.
Usage
Each currency has a uniquecode, a name, and optional symbol and disabled properties. The code is the stable selection identifier. The picker does not ship a currency catalogue or choose an application default.
defaultValue for uncontrolled selection. For controlled selection, pass value and update it from onValueChange. The callback receives the next code or null and Dropdown selection details containing event, reason, trigger, cancel, and isCanceled. Call details.cancel() to preserve the current selection and keep the popup open. Selecting the current code does not emit another change.
null clears the selection. An empty string remains a valid code and does not clear it. An unknown value stays unchanged and appears as its raw code in the trigger; it does not add an option to the catalogue. A later controlled update or catalogue change updates the trigger and selected row.
Advanced composition
CurrencyPicker.Root prepares the catalogue and owns selection for both parts. It adds no DOM element and must be inside Dropdown.Root. Keep Trigger and Options under the same picker root, including when the options live in another dropdown page. The root’s render-function children expose value, selectedCurrency, and disabled for caller-owned labels and supporting content.
Root.closeOnSelect defaults to true; use false to keep the popup open after choosing a currency. Arrow keys, Home, and End move focus without changing the value. Enter, Space, or pointer activation selects an enabled option. Disabled currencies stay visible and cannot be selected.
Search and ordering
Options are searchable by default. Search ignores surrounding whitespace and matches codes, names, symbols, and the defaultName (CODE) label without case sensitivity, using the same rules in every browser locale. getSearchText on the root replaces the searchable text for each currency. Display customization and search text are independent.
Results retain catalogue order. Set selectedFirst on the shorthand or root to move the selected currency before the other matches. A query that excludes it also removes its row. An unknown value does not create a selected result. Empty results show emptyLabel in a status region.
Set Options.searchable={false} to omit the search field. Options.searchProps targets the native search input, including its ref, render, accessible attributes, and controlled value or uncontrolled defaultValue. searchProps.onValueChange receives the query. In shorthand use, pass these options through optionsProps.
The search field receives focus when a searchable picker opens. Enter with a nonempty query activates the first enabled result. With an empty query, move focus to an option before selecting it. Search activation during IME composition and fresh search on reopen remain subject to the shared Dropdown search and page-session contracts.
Presentation and native targets
The trigger shows the selected code by default.renderValue receives { value, selectedCurrency, disabled } to customize that display without looking up the currency again. Trigger.children overrides the value display, and Trigger.placeholder supplies the empty display. getOptionLabel customizes each option’s content, with the default Name (CODE) label. Currency names, symbols, labels, and option content belong to the caller.
The shorthand’s native button attributes, event handlers, className, style, ref, and render target its trigger. triggerProps customizes that same button. Use optionsProps for the options wrapper div and its nested searchProps for the input. contentProps customizes Dropdown’s popup. open, defaultOpen, and onOpenChange coordinate the shorthand’s open state.
In compound use, native attributes, ref, and render on Trigger target its button, while those on Options target its wrapper div. Options.listLabel names only the inner selection listbox. Forward the supplied props and ref from a custom render component. Wrapper styling does not change the input’s native target.
Set disabled on the shorthand or root to disable opening, search, and selection. A part’s disabled prop can additionally disable that part. Selection is a picker value; native form submission, reset, required validation, and Field integration remain outside this API.
Labels and application integration
searchLabel defaults to Search and supplies the search placeholder and accessible name. emptyLabel defaults to No results and accepts content. Supply localized source labels, an accessible trigger name, and any placeholder from your application. Dropdown content takes the trigger name unless a Dropdown.Title or explicit content label names it. The selection listbox takes the registered Dropdown title or trigger name by default. Set Options.listLabel to give only that listbox its own accessible name, or pass optionsProps.listLabel in shorthand use. Native aria-label and aria-labelledby on Options label only its wrapper. The trigger keeps its own accessible name.
The application owns amount editing, currency storage, formatting, catalogue loading, and its initial value. An adapter should map stored currency codes and clearing behavior to value and onValueChange, preserving the application’s formatting and fallback rules. Keep translated currency names and labels in the application.
Front-component renderer
The React and Preact sandbox fixtures cover shorthand and compound search and selection, disabled controls and options, trigger refs, null clearing, external controlled updates, reopening, and Escape focus restoration. They also verify that clearing an earlier query and typing$ preserves the symbol query.
Popup visibility, geometry, scrolling, and dismissal depend on the shared renderer’s Dropdown and portal support. The picker uses that shared implementation.
Props
ReactNode
Caller-owned trigger content that overrides the selected value display.
string | ((state: PopoverTriggerState) => string | undefined)
Class applied to the trigger button.
boolean
Whether committing an enabled option closes the dropdown. Defaults to true. A canceled selection never closes automatically.
Omit<DropdownContentProps, "children">
Dropdown popup props, including placement, width, and accessible attributes.
readonly CurrencyPickerOption[]
required
Available currencies in display order. Each code is a unique stable identifier; name and optional symbol are caller-owned data. A currency can be disabled.
boolean
Whether the popup is initially open when uncontrolled.
string | null
default:"null"
Initial uncontrolled currency code, or null for an empty selection. Defaults to null.
boolean
default:"false"
Disables opening, search, and every currency option.
((currency: CurrencyPickerOption) => ReactNode)
default:"Name (CODE)"
Returns caller-owned content for a currency option. Defaults to Name (CODE). Display content does not change the search text.
((currency: CurrencyPickerOption) => string)
default:"Name (CODE) and symbol"
Returns searchable text for a currency. Defaults to Name (CODE) and its optional symbol. Search trims the query and matches without case sensitivity.
string
ID forwarded to the trigger button.
boolean
default:"true"
Whether render composes a native button. Set false for a custom non-button element so Base UI supplies button interaction.
((event: DropdownDismissEvent) => void)
Called before Escape closes the popup. Call event.preventDefault() to keep it open.
((event: DropdownDismissEvent) => void)
Called before an outside press or Tab out closes the popup. Call event.preventDefault() to keep it open.
((open: boolean) => void)
Called with the next open state when the popup opens or closes.
((value: string | null, eventDetails: DropdownSelectionGroupChangeEventDetails) => void)
Called with the next code or null and cancellable Dropdown selection details: event, reason, trigger, cancel and isCanceled. Calling cancel() preserves selection and prevents automatic close. Repeated single selection does not emit a change.
boolean
Whether the popup is open. Use with onOpenChange to control it.
CurrencyPickerOptionsProps
Props for the options wrapper div, listLabel, and search behavior. Native input customization belongs in optionsProps.searchProps.
ReactNode
Trigger content displayed when the selected value is null.
Ref<HTMLButtonElement>
Ref to the trigger button, or the element composed through render.
ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, PopoverTriggerState>
Replaces the native trigger button. Forward the supplied props and ref when rendering a custom component.
((state: CurrencyPickerState) => ReactNode)
Returns selected trigger content from { value, selectedCurrency, disabled }. The default display is the raw code, or the trigger placeholder when null. Trigger children override it.
boolean
default:"false"
Moves the matching selected currency before other results. Defaults to false, preserving catalogue order.
CSSProperties | ((state: PopoverTriggerState) => CSSProperties | undefined)
Inline styles applied to the trigger button.
CurrencyPickerTriggerProps
Props for the trigger button, including native attributes, ref, render, placeholder, and caller-owned children. These override shorthand trigger props.
string | null
Controlled currency code or null for an empty selection. Undefined leaves selection uncontrolled. Empty and unknown strings remain identifiers.
CurrencyPicker.Root
ReactNode | ((state: CurrencyPickerState) => ReactNode)
required
Picker parts and supporting content, or a render function receiving { value, selectedCurrency, disabled }. Root owns selection and prepared data without adding a DOM element.
boolean
Whether committing an enabled option closes the dropdown. Defaults to true. A canceled selection never closes automatically.
readonly CurrencyPickerOption[]
required
Available currencies in display order. Each code is a unique stable identifier; name and optional symbol are caller-owned data. A currency can be disabled.
string | null
default:"null"
Initial uncontrolled currency code, or null for an empty selection. Defaults to null.
boolean
default:"false"
Disables the trigger, search input, and every currency option.
((currency: CurrencyPickerOption) => ReactNode)
default:"Name (CODE)"
Returns caller-owned content for a currency option. Defaults to Name (CODE). Display content does not change the search text.
((currency: CurrencyPickerOption) => string)
default:"Name (CODE) and symbol"
Returns searchable text for a currency. Defaults to Name (CODE) and its optional symbol. Search trims the query and matches without case sensitivity.
((value: string | null, eventDetails: DropdownSelectionGroupChangeEventDetails) => void)
Called with the next code or null and cancellable Dropdown selection details: event, reason, trigger, cancel and isCanceled. Calling cancel() preserves selection and prevents automatic close. Repeated single selection does not emit a change.
((state: CurrencyPickerState) => ReactNode)
Returns selected trigger content from { value, selectedCurrency, disabled }. The default display is the raw code, or the trigger placeholder when null. Trigger children override it.
boolean
default:"false"
Moves the matching selected currency before other results. Defaults to false, preserving catalogue order.
string | null
Controlled currency code or null for an empty selection. Undefined leaves selection uncontrolled. Empty and unknown strings remain identifiers.
CurrencyPicker.Trigger
ReactNode
Caller-owned trigger content that overrides the selected value display.
string | ((state: PopoverTriggerState) => string | undefined)
Class applied to the trigger button.
boolean
default:"false"
Additionally disables the native trigger button. Root disabled state always takes precedence.
string
ID forwarded to the trigger button.
boolean
default:"true"
Whether render composes a native button. Set false for a custom non-button element so Base UI supplies button interaction.
ReactNode
Trigger content displayed when the selected value is null.
Ref<HTMLButtonElement>
Ref to the trigger button, or the element composed through render.
ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, PopoverTriggerState>
Replaces the native trigger button. Forward the supplied props and ref when rendering a custom component.
CSSProperties | ((state: PopoverTriggerState) => CSSProperties | undefined)
Inline styles applied to the trigger button.
CurrencyPicker.Options
string
Class applied to the options wrapper div.
boolean
default:"false"
Additionally disables search and every currency option. Root disabled state always takes precedence.
ReactNode
default:"No results"
Content announced when no currencies match. Defaults to No results.
string
Accessible name for the selection listbox. Defaults to the registered Dropdown title or trigger name. Native accessible attributes on Options target only its wrapper.
Ref<HTMLDivElement>
Ref to the options wrapper div, or the element composed through render.
ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, {}>
Replaces the non-interactive wrapper div. Forward the supplied props and ref when rendering a custom component. Use searchProps.render to customize the input.
boolean
default:"true"
Renders a search input above the options. Defaults to true.
string
default:"Search"
Search placeholder and accessible name. Defaults to Search.
DropdownSearchProps
Native input attributes, ref, render, and controlled or uncontrolled query props forwarded to Dropdown.Search. Use value with onValueChange or defaultValue.
CSSProperties
Inline styles applied to the options wrapper div.