---
id: "packages/active-ui/currency-combobox"
title: "CurrencyCombobox"
description: "A searchable currency choice by ISO 4217 code, from the list and names your application supplies."
url: "/packages/active-ui/currency-combobox"
locale: "en"
revision: "e2dca56c9574eddd"
---

# CurrencyCombobox

`CurrencyCombobox` picks a currency. The value is its ISO 4217 code; the reader sees `EUR - Euro`
and can search on the code or the name. It is a thin layer over
[SearchCombobox](/packages/active-ui/search-combobox), which does the menu, search and keyboard.

**Example: A currency by its code**

Client: Runs entirely in your browser. Source: `examples/ui/currency-combobox.tsx`.

```tsx
// apps/docs/examples/ui/currency-combobox.tsx
'use client';

import {useMemo, useState} from 'react';

import {CurrencyCombobox} from '@workspace/active-ui/components/composed/currency-combobox';
import {
  Field,
  FieldDescription,
  FieldLabel,
} from '@workspace/active-ui/components/primitives/field';

// The list and its order are the application's: here the euro first.
const CODES = ['EUR', 'USD', 'GBP', 'CHF', 'SEK', 'DKK', 'NOK', 'PLN', 'JPY'];

/**
 * A currency by its ISO 4217 code. The names come from the browser's
 * `Intl.DisplayNames`, in the reader's language; the code is shown first
 * and is searchable too (try "fr" for the Swiss franc).
 */
export default function CurrencyComboboxExample() {
  const [currency, setCurrency] = useState('EUR');
  const options = useMemo(() => {
    const names = new Intl.DisplayNames(['en'], {type: 'currency'});
    return CODES.map((code) => ({code, name: names.of(code) ?? code}));
  }, []);
  return (
    <Field className="w-full max-w-xs">
      <FieldLabel htmlFor="currency">Currency</FieldLabel>
      <CurrencyCombobox
        id="currency"
        value={currency}
        onValueChange={setCurrency}
        options={options}
        locale="en"
        placeholder="Choose a currency"
        searchLabel="Search currencies"
        searchPlaceholder="Search…"
        emptyText="No currency found."
        aria-describedby="currency-value"
      />
      <FieldDescription id="currency-value">
        Value: <code>{currency || "''"}</code>
      </FieldDescription>
    </Field>
  );
}
```

## What the composition adds

- **A code as the value**, `''` when nothing is chosen.
- **The code is searchable** next to the name, and shown first with `showCode` (default `true`).

It owns no list, no names, no order and no default: there is no built-in set of currencies.

## Usage

```tsx
import {CurrencyCombobox} from '@workspace/active-ui/components/composed/currency-combobox';

<CurrencyCombobox
  id="currency"
  value={currency} // 'EUR' or ''
  onValueChange={setCurrency}
  options={[{code: 'EUR', name: 'Euro'}]}
  locale="en"
  placeholder="Choose a currency"
  searchLabel="Search currencies"
  searchPlaceholder="Search…"
  emptyText="No currency found."
/>;
```

## What your application provides

- The currencies in the order to show, with names in the reader's language, for example from
  `Intl.DisplayNames` as in the example. A stored code you no longer offer stays selectable only
  when it stays in the list.
- A default, set in the form, and whether the field is required.

## Accessibility

As [SearchCombobox](/packages/active-ui/search-combobox): name the button with `FieldLabel htmlFor`
its `id`.

## API

| Prop | Type | Required | Description |
| --- | --- | --- | --- |
| `emptyText` | `string` | yes | Text when the search finds nothing. Supplied translated. |
| `locale` | `string` | yes | The reader's language, for matching the query against names and codes. It does not produce the names: those arrive in `options`. |
| `onValueChange` | `(value: string) => void` | yes | Receives the chosen code, or `''` when the choice is cleared. |
| `options` | `readonly CurrencyComboboxOption[]` | yes | Every currency to choose from, **in the order they are shown**.  Required, and there is no built-in list: which currencies a product offers, their names, and which come first (a priority block, the currencies of a country) are the host's. A stored code the runtime no longer knows stays selectable only when the caller keeps it in this list. |
| `placeholder` | `string` | yes | Button text while nothing is chosen. Supplied translated. |
| `searchLabel` | `string` | yes | Accessible name of the search field in the menu. Supplied translated. |
| `searchPlaceholder` | `string` | yes | Text in the search field. Supplied translated. |
| `value` | `string` | yes | The chosen code, or `''` when nothing is chosen. |
| `aria-describedby` | `string` | no | The ids of the description and error of the field, on the button. |
| `aria-invalid` | `"false" \| "grammar" \| "spelling" \| "true" \| boolean` | no | The validation state of the field, on the button. |
| `className` | `string` | no | Classes for the button. |
| `disabled` | `boolean` | no | Disables the button. |
| `id` | `string` | no | The `id` of the button, for `<FieldLabel htmlFor>`. |
| `readOnly` | `boolean` | no | Shows the choice without allowing a change; see `SearchCombobox`. |
| `required` | `boolean` | no | Marks the choice as required for assistive technology. Whether it is required, and when (only once an amount is entered, say), is the caller's schema; this component blocks nothing. |
| `showCode` | `boolean` | no | Shows the code before the name (`EUR - Euro`). Default `true`: a currency field stores a code and its reader usually knows it. Off, the code still takes part in searching. |

**CurrencyComboboxOption**

```ts
interface CurrencyComboboxOption {
  code: string;
  name: string;
}
```

One currency the caller offers.

Three separate things meet here and none follows from another: the `code`
is DATA (the ISO 4217 identity a record stores), the `name` is text in the
reader's language (how the code is called), and how an AMOUNT in this
currency is written is the presentation's business, not this picker's.

**CurrencyComboboxProps**

```ts
interface CurrencyComboboxProps {
  value: string;
  onValueChange: (value: string) => void;
  options: readonly CurrencyComboboxOption[];
  locale: LocaleCode;
  showCode?: boolean;
  placeholder: string;
  searchLabel: string;
  searchPlaceholder: string;
  emptyText: string;
  disabled?: boolean;
  readOnly?: boolean;
  required?: boolean;
  className?: string;
  id?: string;
  'aria-describedby'?: string;
  'aria-invalid'?: AriaAttributes['aria-invalid'];
}
```
