Currency Input

A specialized input component for entering monetary values with currency selection. Combines a numeric input with an integrated currency selector dropdown featuring country flags and currency codes.

Basic Usage

import { CurrencyInput, USFlag, EUFlag, GBFlag, NOFlag, CHFlag, currencies } from '@/components'

const currenciesWithFlags = [
  { ...currencies.USD, flag: <USFlag /> },
  { ...currencies.EUR, flag: <EUFlag /> },
  { ...currencies.GBP, flag: <GBFlag /> },
  { ...currencies.NOK, flag: <NOFlag /> },
  { ...currencies.CHF, flag: <CHFlag /> },
]

<CurrencyInput currencies={currenciesWithFlags} />
$

With Label and Hint

Add a label and helper text to guide users.

<CurrencyInput
  label="Amount"
  hint="Enter the transaction amount"
  currencies={currenciesWithFlags}
/>
$

Enter the transaction amount

Required Field

Use the required prop to show a required indicator (blue asterisk). Add showInfoIcon for additional context.

<CurrencyInput
  label="Payment Amount"
  hint="This is a hint text to help users."
  currencies={currenciesWithFlags}
  required
  showInfoIcon
/>
$

This is a hint text to help users.

Sizes

The input comes in three sizes: small (36px), medium (40px, default), and large (44px).

Small (36px)

$

Medium (40px) - Default

$

Large (44px)

$

Small

<CurrencyInput size="sm" label="Amount" currencies={currenciesWithFlags} />

Medium (Default)

<CurrencyInput size="md" label="Amount" currencies={currenciesWithFlags} />

Large

<CurrencyInput size="lg" label="Amount" currencies={currenciesWithFlags} />

States

The input has multiple visual states: Default (idle), Filled, Error, and Disabled.

Default (Idle)

$

Filled

$

Error

$

Amount must be greater than zero

Disabled

$

Controlled Component

Control the input value and currency selection externally.

const [value, setValue] = useState('')
const [currency, setCurrency] = useState('USD')

<CurrencyInput
  label="Transfer Amount"
  hint={`Current value: ${currency} ${parseFloat(value || '0').toFixed(2)}`}
  currencies={currenciesWithFlags}
  value={value}
  onValueChange={setValue}
  currency={currency}
  onCurrencyChange={setCurrency}
  required
/>
$

Current value: USD 0.00

Without Currency Selector

Hide the currency selector for fixed-currency inputs.

<CurrencyInput
  label="Price (USD only)"
  currency="USD"
  showCurrencySelector={false}
/>
$

Currency selector is hidden

Value Formatting

By default, values are automatically formatted with thousand separators (1234.56 → 1,234.56). This happens on blur.

Disable Formatting

<CurrencyInput
  label="Amount (no formatting)"
  formatValue={false}
/>
$

Raw value: ""

Custom Formatting

Provide a custom formatter function to control how values are displayed.

const customFormatter = (val: string) => {
  const num = parseFloat(val) || 0
  if (num >= 1000) {
    return `${(num / 1000).toFixed(1)}K`
  }
  return num.toFixed(2)
}

<CurrencyInput
  label="Amount (custom format)"
  onFormatValue={customFormatter}
/>
$

Shows K suffix for thousands

Currency Selection

The currency selector supports searching and displays country flags with currency codes.

<CurrencyInput
  label="International Transfer"
  currencies={currenciesWithFlags}
  defaultCurrency="NOK"
/>
kr

Select from multiple currencies

All States Overview

Idle

$

Filled

$

Error

$

Disabled

$

Tree-Shakeable Flags

Flag components are exported individually to support tree-shaking. Import only the flags you need:

// Tree-shakeable: only imports the flags you use
import { USFlag, EUFlag, currencies } from '@/components'

const myCurrencies = [
  { ...currencies.USD, flag: <USFlag /> },
  { ...currencies.EUR, flag: <EUFlag /> },
]

Or import all flags at once (no tree-shaking):

// Convenience: imports all flags
import { currencyFlags, currencyList } from '@/components'

const allCurrencies = currencyList.map(c => ({
  ...c,
  flag: currencyFlags[c.code] ? React.createElement(currencyFlags[c.code]) : null
}))

Accessibility

  • Labels are properly associated with inputs via htmlFor/id
  • aria-describedby connects hint/error text to the input
  • aria-invalid is set when in error state
  • aria-required is set for required fields
  • Currency selector button has proper ARIA labels
  • Full keyboard navigation support for the dropdown

API Reference

CurrencyInput Props

PropTypeDefaultDescription
valuestring-Controlled numeric value (raw, unformatted)
onValueChange(value: string) => void-Callback when value changes
currencystring-Currently selected currency code
onCurrencyChange(code: string) => void-Callback when currency changes
currenciesCurrency[]Default listAvailable currencies to select from
defaultCurrencystring'USD'Default currency code (uncontrolled)
labelstring-Label text above the input
hintstring-Hint text below the input
errorboolean | stringfalseError state or error message
size'sm' | 'md' | 'lg''md'Input size variant
requiredbooleanfalseMark as required
disabledbooleanfalseDisable the input
showOptionalBadgebooleanfalseShow "(Optional)" badge
showInfoIconbooleanfalseShow info icon in label
formatValuebooleantrueEnable auto-formatting
formatOptionsIntl.NumberFormatOptions-Customize number formatting
onFormatValue(value: string) => string-Custom formatter function
showCurrencySelectorbooleantrueShow currency selector dropdown
currencySearchPlaceholderstring'Search currency...'Placeholder for currency search

Currency Interface

interface Currency {
  code: string      // e.g., "USD", "NOK"
  symbol: string    // e.g., "$", "kr"
  name: string      // e.g., "US Dollar", "Norwegian Krone"
  flag?: ReactNode  // Flag icon/component
}

Available Currency Data

The component exports currency data and flags separately for tree-shaking:

ExportDescription
currenciesObject with currency data keyed by code
currencyListArray of all currency data
commonCurrenciesArray of commonly used currencies
getCurrency(code)Helper to get currency by code
USFlag, EUFlag, etc.Individual flag components
currencyFlagsObject mapping codes to flag components