Input Currency
Locale-aware monetary input with formatting, constraints, precision, and step controls.
Input Currency
InputCurrency is a numeric form field for prices, budgets, payments, and other monetary values. It formats the displayed value with Intl.NumberFormat, supports locale-specific separators and currency presentation, and exposes numeric values through callbacks.
Basic usage
import { InputCurrency } from '@mosmox/ui';
<InputCurrency label="Price" currency="USD" defaultValue={1299.99} />The field displays the currency symbol, grouping separators, and fraction digits according to currency, locale, and the fraction options.
Controlled and uncontrolled values
Use defaultValue when the component should manage its own value. Use value and onChange when the parent owns the value:
const [budget, setBudget] = useState<number | null>(1000);
<InputCurrency
currency="USD"
value={budget}
onChange={(value, formattedValue) => {
setBudget(value);
console.log('Formatted:', formattedValue);
}}
/>value={null} represents an empty value. onChange receives the numeric value (number or null) and the formatted string. onBlur receives the committed numeric value after the current text is parsed, constrained, and formatted.
Currency and locale
currency is passed to Intl.NumberFormat and normally uses an ISO 4217 currency code. locale controls decimal separators, grouping separators, symbol placement, and localized currency names.
<InputCurrency currency="UAH" locale="uk-UA" defaultValue={2499.99} />
<InputCurrency currency="EUR" locale="de-DE" defaultValue={8900} />
<InputCurrency currency="GBP" locale="en-GB" currencyDisplay="code" defaultValue={4250.75} />currencyDisplay accepts symbol, narrowSymbol, code, or name.
Minimum, maximum, and step
<InputCurrency currency="USD" min={0} max={100000} step={50} defaultValue={500} />minsets the lower numeric bound.maxsets the upper numeric bound.stepcontrols the increment and decrement amount; default1.
Bounds are applied when a value is emitted and when the field loses focus. Arrow Up, Arrow Down, and the visible controls use step. The decrease/increase buttons become disabled at the corresponding bound. If min or max is omitted, that side has no limit.
Precision and fraction digits
<InputCurrency currency="USD" precision={2} defaultValue={12.5} />
<InputCurrency currency="JPY" locale="ja-JP" precision={0} defaultValue={120000} />
<InputCurrency currency="USD" minFractionDigits={2} maxFractionDigits={4} />precisionsets both minimum and maximum fraction digits.minFractionDigitsandmaxFractionDigitscontrol the two sides independently.
When no precision is supplied, the component uses a minimum of 0 and a maximum of 2 fraction digits. Independent fraction props take precedence over precision for the corresponding side.
Formatting options
<InputCurrency currency="USD" useGrouping={false} defaultValue={1234.5} />
<InputCurrency currency="USD" signDisplay="always" defaultValue={125} />useGrouping controls thousands separators and defaults to true. signDisplay accepts auto, always, or exceptZero and defaults to auto. While focused, the input exposes an editable numeric representation; on blur it returns to the localized currency format.
Controls, clearing, and states
<InputCurrency
label="Order total"
name="amount"
currency="USD"
clearable
description="The amount charged to the customer."
prefix={<span aria-hidden="true">≈</span>}
suffix={<span aria-hidden="true">per month</span>}
/>controlsshows increment/decrement buttons and defaults totrue.clearableshows a Clear amount button when a value exists and defaults tofalse.disabledprevents interaction and disables the input.readOnlyprevents editing and hides active controls.loadingdisables the input and controls while showing a loading status.errormarks the field invalid and renders an alert message.descriptionrenders supporting text and associates it with the input.prefixandsuffixrender custom adornments.sizeacceptssm,default, orlg.
Events
<InputCurrency
currency="USD"
min={0}
max={5000}
onChange={(value, formattedValue) => {
console.log(value); // number | null
console.log(formattedValue); // localized string
}}
onBlur={(value) => console.log('Committed:', value)}
/>onChange runs as numeric text changes and receives the bounded numeric value plus its formatted representation. onBlur runs after the current text is parsed, clamped to min/max, stored, and formatted.
Accessibility and form integration
The input uses role="spinbutton" and exposes aria-valuemin, aria-valuemax, and aria-valuenow when the corresponding values exist. A visible label is associated with the input. If there is no visible label, provide aria-label.
<InputCurrency
aria-label="Monthly budget"
name="monthlyBudget"
id="monthly-budget"
placeholder="Enter amount"
currency="USD"
/>Arrow Up/Down step the value. Validation messages passed through error use an alert region.
API reference
| Prop | Type | Default | Description |
|---|---|---|---|
label | ReactNode | — | Visible field label. |
description | ReactNode | — | Supporting text associated with the input. |
error | ReactNode | — | Validation message and invalid state. |
currency | string | 'USD' | Currency code passed to Intl.NumberFormat. |
locale | string | 'en-US' | Formatting locale. |
currencyDisplay | 'symbol' | 'narrowSymbol' | 'code' | 'name' | 'symbol' | Currency presentation. |
value | number | null | — | Controlled numeric value. |
defaultValue | number | — | Initial uncontrolled value. |
onChange | (value: number | null, formattedValue: string) => void | — | Numeric and formatted value event. |
onBlur | (value: number | null) => void | — | Committed value event. |
min | number | — | Minimum numeric value. |
max | number | — | Maximum numeric value. |
step | number | 1 | Arrow/control increment. |
precision | number | — | Sets minimum and maximum fraction digits. |
minFractionDigits | number | 0 | Minimum fraction digits unless overridden by precision. |
maxFractionDigits | number | 2 | Maximum fraction digits unless overridden by precision. |
useGrouping | boolean | true | Shows grouping separators. |
signDisplay | 'auto' | 'always' | 'exceptZero' | 'auto' | Sign formatting. |
controls | boolean | true | Shows increment/decrement controls. |
clearable | boolean | false | Shows a clear button when populated. |
disabled | boolean | false | Disables input and controls. |
readOnly | boolean | false | Prevents editing and control interaction. |
loading | boolean | false | Shows loading state and disables interaction. |
size | 'sm' | 'default' | 'lg' | 'default' | Field density. |
prefix | ReactNode | — | Leading adornment. |
suffix | ReactNode | — | Trailing adornment. |
placeholder | string | localized zero | Placeholder text. |
name | string | — | Native form field name. |
id | string | generated | Input ID used by the label. |
aria-label | string | — | Accessible name when no visible label exists. |
className | string | — | Root field class. |
style | CSSProperties | — | Root inline styles. |
InputCurrency does not expose imperative methods through a forwarded ref. Use controlled value, onChange, and onBlur for application logic.