Source: https://monarchui.dev/components/money/

Components · Billing

# Money

An amount of one currency, formatted by Intl.NumberFormat in tabular figures.

@rookcom/monarch-react

Component

## Locales and minor units

## Usage examples

### Compact, signs and negatives

## Purpose

Displays a monetary amount the same way everywhere: localised, in its own currency, from minor units without floating-point loss, with an accessible full value when shortened.

### Use when

- Prices, invoice lines, payroll figures, renewal costs and balances.
- Amounts stored as integer minor units (cents, paise) next to an ISO 4217 currency code.

### Avoid when

- Entering an amount: use a currency input.
- Adding amounts in different currencies: list them per currency instead; Money never converts.

## Design principles

- One amount, one currency. Conversion and summing across currencies stay in the product.
- Tabular figures and no wrapping, so columns of amounts line up.
- The sign carries the meaning; colour (`toneNegative`) only reinforces it.
- Shortened amounts never hide the real value: compact notation keeps the full amount for screen readers and as a hover title.

## API reference

```tsx
import { Money, currencyDigits, formatMoney } from '@rookcom/monarch-react';
```

| Export | Kind | Rendering | Root class |
| --- | --- | --- | --- |
| `Money` | component | server-safe | `.mn-money` |
| `currencyDigits` | utility | server-safe | – |
| `formatMoney` | utility | server-safe | – |

The ref and native attributes go to the root `<span>`.

`formatMoney(amount, currency, options)` returns the same string for exports, charts and `aria-label`s; `currencyDigits(code)` gives the minor-unit digits (USD 2, JPY 0, KWD 3).

Decimal strings (`"1234.50"`) and bigints are formatted exactly; they need a runtime with Intl.NumberFormat v3 (all current evergreen browsers and Node 20+).

Generated from the TypeScript declarations of `packages/react/src/components/billing/money`.

## Properties

With `minorUnits`, `amount` must be an integer; a fractional string throws a RangeError.

### `Money`

A formatted amount in tabular figures. With `notation="compact"` the short form is shown and the full amount is given to assistive technology and as a hover title.

| Prop | Type | Description |
| --- | --- | --- |
| `amount` required | `MoneyAmount \| null` | The amount. `null` or `undefined` renders `emptyLabel`. |
| `currency` required | `string` | ISO 4217 code, e.g. `USD`, `EUR`, `INR`. |
| `className` | `string` |  |
| `currencyDisplay` | `"symbol" \| "name" \| "code" \| "narrowSymbol"` | How the currency is written: `symbol` ($), `narrowSymbol`, `code` (USD) or `name` (US dollars). Default `symbol`. |
| `currencySign` | `"standard" \| "accounting"` | `accounting` writes negatives in parentheses where the locale does. Default `standard`. |
| `emptyLabel` | `string` | Shown when `amount` is missing. Default "—", read as "No amount". |
| `id` | `string` |  |
| `locale` | `string` | BCP 47 locale, e.g. `en-IN`. Default: the runtime locale. |
| `maximumFractionDigits` | `number` |  |
| `minimumFractionDigits` | `number` |  |
| `minorUnits` | `boolean` | `amount` is in the currency's minor units (cents, paise): `1999` with USD is $19.99. |
| `notation` | `"compact" \| "standard"` | `compact` writes $1.2M. Default `standard`. |
| `signDisplay` | `"auto" \| "always" \| "exceptZero" \| "never"` | `Intl.NumberFormat` sign display. `exceptZero` shows +/− for gains and losses. Default `auto`. |
| `toneNegative` | `boolean` | Colour negative amounts with the danger text colour (`data-negative` is set either way). The minus sign or parentheses always carry the meaning. Default `false`. |

## Variants

| Prop | Values | Description |
| --- | --- | --- |
| `notation` | `'standard'``'compact'` | `compact` writes $1.3M and adds the full value for assistive technology (`data-notation`). |
| `signDisplay` | `'auto'``'always'``'exceptZero'``'never'` | `exceptZero` writes +$42.00 for gains. |
| `currencyDisplay` | `'symbol'``'narrowSymbol'``'code'``'name'` | $, $, USD or “US dollars”. |
| `currencySign` | `'standard'``'accounting'` | `accounting` writes negatives in parentheses where the locale does. |

## States

| State | Exposed as | Behaviour |
| --- | --- | --- |
| Negative | `data-negative` | Always set for amounts below zero; `toneNegative` adds `data-tone="danger"`. |
| Empty | `data-empty` | `amount` null or undefined: an em dash read as “No amount”, or `emptyLabel`. |
| Compact | `data-notation="compact"` | Short visible text, full amount in visually hidden text and `title`. |

## Interaction behaviour

- None. In compact notation the native `title` shows the full amount on hover; screen readers read the full amount directly.

## Keyboard support

Not interactive, so there is no keyboard behaviour.

## Accessibility

Role

none (inline text)

Accessible name

The formatted amount is the text itself.

- Compact amounts render the short form `aria-hidden` and the full form in visually hidden text, so “$1.3M” is read as “$1,250,000.00”.
- The empty dash is hidden from screen readers and replaced by “No amount”.
- Negative colour is never the only cue: the minus sign or parentheses are always present.

## Responsive behaviour

- Amounts never wrap (`white-space: nowrap`). Use `notation="compact"` where a column is narrow on phones.

## Theme support

- Inherits the surrounding text colour; `toneNegative` uses `--mn-color-danger-strong`, which meets AA in every theme.
- The empty state uses `--mn-color-text-muted`.

## Do and don't

### Do

- Store and pass integer minor units with `minorUnits`; it avoids floating-point rounding.
- Pass the viewer’s `locale` so separators and symbol placement match their region.
- Show one line per currency when totals span currencies.

### Don't

- Do not add amounts of different currencies together before displaying them.
- Do not rely on red alone to show a negative amount.
- Do not shorten amounts with `compact` where the exact figure is the point, such as an invoice total.

## Related components

- [StatCard](https://monarchui.dev/components/stat-card/): Headline figures; pass a Money as the value.
- [DescriptionList](https://monarchui.dev/components/description-list/): Label and amount pairs in a summary.
- [DataTable](https://monarchui.dev/components/data-table/): Right-aligned amount columns.
- [DeltaIndicator](https://monarchui.dev/components/delta-indicator/): Planned up/down change next to an amount.

## Dependencies

| Kind | Depends on |
| --- | --- |
| npm packages | `react` |
| Monarch components | [VisuallyHidden](https://monarchui.dev/components/visually-hidden/) |

## Testing coverage

- Formats in en-US, de-DE and en-IN.
- Minor units use the currency’s digits (USD, JPY, KWD), including small and negative values.
- Bigint and decimal-string amounts keep full precision; fractional minor units throw.
- Compact notation, sign display, accounting sign and currency display.
- Compact amounts expose the full value to assistive technology and as a title, without duplicating equal text.
- Negative marking and opt-in danger tone; empty state and `emptyLabel`.
- Forwards the ref and keeps a consumer `title`.

| Check | Covered |
| --- | --- |
| Axe in jsdom | Yes |
| Server rendering | Yes |
| Browser suites | Visual baselines: /__gallery; Cross-browser axe: /components/money |

Tests: `packages/react/src/components/billing/money`

## All example code

### Locales and minor units

```tsx
import { Money } from '@rookcom/monarch-react';

<Money amount={129900} currency="USD" minorUnits locale="en-US" />
<Money amount={129900} currency="EUR" minorUnits locale="de-DE" />
<Money amount={12990000} currency="INR" minorUnits locale="en-IN" />
<Money amount={4500} currency="JPY" minorUnits locale="ja-JP" />
```

### Compact, signs and negatives

```tsx
import { Money } from '@rookcom/monarch-react';

<Money amount={2_480_000} currency="USD" locale="en-US" notation="compact" />
<Money amount={1250} currency="USD" locale="en-US" signDisplay="exceptZero" />
<Money amount={-1250} currency="USD" locale="en-US" toneNegative />
<Money amount={-1250} currency="USD" locale="en-US" currencySign="accounting" />
<Money amount={null} currency="USD" />
```
