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"
/>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-describedbyconnects hint/error text to the inputaria-invalidis set when in error statearia-requiredis set for required fields- Currency selector button has proper ARIA labels
- Full keyboard navigation support for the dropdown
API Reference
CurrencyInput Props
| Prop | Type | Default | Description |
|---|---|---|---|
| value | string | - | Controlled numeric value (raw, unformatted) |
| onValueChange | (value: string) => void | - | Callback when value changes |
| currency | string | - | Currently selected currency code |
| onCurrencyChange | (code: string) => void | - | Callback when currency changes |
| currencies | Currency[] | Default list | Available currencies to select from |
| defaultCurrency | string | 'USD' | Default currency code (uncontrolled) |
| label | string | - | Label text above the input |
| hint | string | - | Hint text below the input |
| error | boolean | string | false | Error state or error message |
| size | 'sm' | 'md' | 'lg' | 'md' | Input size variant |
| required | boolean | false | Mark as required |
| disabled | boolean | false | Disable the input |
| showOptionalBadge | boolean | false | Show "(Optional)" badge |
| showInfoIcon | boolean | false | Show info icon in label |
| formatValue | boolean | true | Enable auto-formatting |
| formatOptions | Intl.NumberFormatOptions | - | Customize number formatting |
| onFormatValue | (value: string) => string | - | Custom formatter function |
| showCurrencySelector | boolean | true | Show currency selector dropdown |
| currencySearchPlaceholder | string | '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:
| Export | Description |
|---|---|
currencies | Object with currency data keyed by code |
currencyList | Array of all currency data |
commonCurrencies | Array of commonly used currencies |
getCurrency(code) | Helper to get currency by code |
USFlag, EUFlag, etc. | Individual flag components |
currencyFlags | Object mapping codes to flag components |