Skip to content

FX Converter

Beta
Get Ritla UI

Two currency fields with a swap button between them, the rate and when it was taken, a fees card ending with the total, and a note.

Preview

Mirrored is the same English content laid out right to left: it separates a mirroring bug from a translation one.

PreviewCode
EnglishMirroredArabic
LTR →

Installation

  1. Add the component

    npx ritla add fx-converter

    Also works with shadcn: npx shadcn@latest add @ritla/fx-converter

  2. Dependencies it brings

    @phosphor-icons/react

  3. Or copy by hand

    Installing by hand copies the component's source into your project. The source comes with a Ritla UI license, so the CLI is the short way to the same files.

Usage

fx-converter.tsx
import { FxConverter } from "@/components/ui/fx-converter";<FxConverter  send={{ label: "You send", amount, onAmountChange: setAmount, currency: { code: "SAR", country: "SA" } }}  receive={{ label: "Recipient gets", amount: converted, currency: { code: "USD", country: "US" } }}  onSwap={swap}  labels={{ swap: "Swap currencies", changeCurrency: "Change currency" }}  rate="1 SAR = 0.2663 USD"  rateTime="Mid-market rate at 07:17 UTC"  fees={[{ label: "Our fee", value: "SAR 5.00" }, { label: "Total to pay", value: "SAR 1,005.00" }]}/>

API reference

FxConverter

PropTypeDefaultDescription
send / receiveSwapFieldNoneEach side: label, amount, onAmountChange (leave it out for read only), currency, onCurrencyClick, caption. The same field as the Swap card's.
onSwap() => voidNoneSwaps the two sides.
labels{ swap, changeCurrency }NoneButton names in the page language.
ratestringNoneThe rate line, left to right.
rateTimeReactNodeNoneWhen the rate was taken.
fees{ label, value }[]NoneThe fees card, in order; the last line is the total. With no lines there is no card.
noteReactNodeNoneThe line at the bottom.

Accessibility

ARIA

  • Each amount is a labelled input and the converted side is read only. The swap button sits between the fields in the tab order too.
  • The rate is a polite live region: a changed amount or currency is announced once.

Arabic and RTL notes

Mirrors

  • The amount is on the right, the currency pill on the left, and the labels start on the right.

Does not mirror

  • The swap arrows point up and down and never mirror.
  • The rate line, the amounts and the currency codes stay left to right.
Numerals
Amounts can be typed in Latin or Arabic-Indic digits, with the Arabic decimal separator «٫»; read them with parseAmount from @/lib/money.
Arabic typography
heading-28 Semibold amounts and a body-16 Semibold rate.