Skip to content

Payments


24. AmountInput

The hardest input in fintech. Get this wrong and nothing else matters.

<AmountInput
  currency="USD"
  value={amount}
  onChange={setAmount}
  max={availableBalance}
  onMaxClick={() => setAmount(availableBalance)}
/>

The rules

  • type="text" + inputMode="decimal". Never type="number" — it has scroll-wheel increment (which will silently change someone's payment amount), inconsistent decimal parsing across locales, and unstyleable spinners.
  • 16px minimum font size or iOS Safari zooms the viewport on focus and never zooms back.
  • Parse permissively, format on blur. Accept 1,234.56, 1234,56, 1 234.56, $1234.56, 1.2k. Reject nothing a human would type. Format canonically when they leave the field.
  • Never reformat mid-typing. Inserting a thousands separator while someone is typing moves the caret and is the single most infuriating input bug in fintech. Format on blur only.
  • Caret preservation if you must transform during input — measure the caret offset from the right, not the left.
  • Never block paste.
  • Locale-aware decimal separator. A German user types 1234,56. Accept it.
  • Currency-aware precision. JPY rejects decimals entirely; KWD accepts three.
  • Max is soft by default. Show "Exceeds available balance of $4,120.00" as an inline error, but let them type it — an overdraft may be legitimate, and blocking input to prevent an invalid state prevents valid ones too.
  • Big. figure-lg (28/32) or larger. This is the most important number on the screen and it should look like it.
  • The symbol is part of the field, at --text-tertiary, not a floating adornment that misaligns as the value grows.

Accessibility

aria-label="Amount in US dollars" · parsed value announced on blur ("one thousand two hundred thirty-four dollars and fifty-six cents") via aria-describedby · errors specific and actionable · aria-invalid on error.

Motion

None on the value. Error message: 140ms opacity + 4px translate. Shake on invalid submit is forbidden — it's a stress signal in a context where the user is already anxious about money.


25. CurrencySelect

Searchable by code, name, and symbol. Recents pinned at the top. Flag optional, code always. Virtualized (180+ currencies). Keyboard typeahead — typing eu selects EUR.

26. PayeeSelect

Fuzzy search across name, account, and reference. Shows last-paid amount and date inline — the single most useful piece of context when choosing a recipient. New-payee flow inline, not a separate route.

27. PaymentForm

amount → payee → method → date → memo. That order — the amount first, because it's what the user came to do and it contextualizes everything after.

  • Progressive disclosure: memo, reference, and attachments behind "Add details".
  • Validation on blur, never per-keystroke.
  • Submit is bottom-anchored on phone, above the safe area and above the keyboard (visualViewport), always visible.
  • The submit button states the amount: Send $12,400.00.
  • Fee and arrival estimate update live below the amount, with a value crossfade — never a count-up.

28. PaymentMethodList

Radio cards with EntityMark, masked number, and any per-method fee/timing difference stated inline. Selected state: 2px --accent border and an --accent-subtle background — and a check glyph, because border color alone fails forced-colors mode.

29. CheckoutSummary

Line items → subtotal (single rule) → fees → tax → total (double rule). Uses the same Rule grammar as the statements. Fees are itemized and named, never a lump "Fees". Multi-currency lines show conversion with the rate and its timestamp.

30. ConfirmPaymentDialog

Amount, destination, timing. In that order. Every time.

Send $12,400.00 to Northwind Ltd?
To account ••••4291 · Arrives 8 Sep
This can't be undone once submitted.
[Cancel]  [Hold to send →]

AlertDialog. Focus lands on Cancel, never on the destructive action. Escape cancels.

For irreversible movements — wires, ACH past cutoff — the confirm is hold-to-confirm (1500ms linear fill, 200ms release). Slow where the user is deciding. Full spec including the keyboard and typed-confirmation fallbacks in motion catalog — this can never be the only path, because gating money behind a motor-skill requirement is an accessibility failure.

31. PaymentStatusTimeline

Submitted → Sent → In transit → Settled, each with a real timestamp and timezone. Failed states show the reason and the remedy. Pending is a state, not a load — a clock icon, never a spinner.

32. PaymentSuccess

The sanctioned delight moment. Circle scale → checkmark stroke draw → details fade up, staggered. Total ≤ 700ms. No confetti, no bounce, no sound. Spec.

Shows the amount, the destination, and the arrival estimate — the three things the user needs before they close the screen.

33. ReceiptSheet

Printable and shareable. Entity, amount, payee, method, reference, timestamp with timezone. Print styles are first-class — this is a document people keep.

34. PayoutSchedule

Upcoming payouts on a calendar or list, with cutoff times stated in the user's timezone. Business days respected, holidays flagged.

35. CardInput

PAN / expiry / CVC. autocomplete="cc-number" | "cc-exp" | "cc-csc", Luhn validation, network detection from the IIN with the mark appearing inline (140ms crossfade, blur-masked). Auto-advance between fields, with backspace returning to the previous field — the detail everyone forgets.

36. BankAccountInput

Routing + account number. ABA checksum validation with the institution name resolved and displayed once valid — instant confirmation that they typed the right bank. IBAN mod-97 validation for international, with country-aware length and formatting.

37. RecurringSchedule

Frequency, start, end condition. Always previews the next three occurrences with resolved dates. "Monthly on the 31st" is ambiguous in February; the preview makes the resolution visible before it surprises anyone.

The 14 components specified here.

Built against this document

The surfaces that implement what this argues — running, computing, or shaped by it.

Told when this spec changes

The docs are the contract the components are built against. When one changes, the component changes with it — and the copy in your repo does not. One email when that happens.

One address, no list rental, unsubscribe in one click.

Works in your QuickBooks Online or Xero file

Get your books closed every month

Lopifi is building AI bookkeeping that keeps your books closed on US GAAP as transactions happen, with a CPA review every quarter, for $200 a month. We’re not open yet.

$200/month when we open. No card now.