Payment Reference

Checks a bank transfer reference against each rail's length and character limits, so the invoice number reaches the payee intact.

StopsTransfer couldn't be matched to the invoice

Installation

pnpm dlx shadcn@latest add https://bollard-ui.vercel.app/r/payment-reference.json

The files land in your project. They're yours to edit.

Usage

payment-reference-usage.tsx
import { PaymentReference } from "@/components/ui/payment-reference"

<PaymentReference
  defaultValue="Payment for invoice #INV-2026-0142"
  expected="INV-2026-0142"
  defaultRail="neft"
  payerName="Tushar Khadde"
/>

What it catches

  • Missing, mistyped or different invoice number
  • Reference longer than the rail keeps, with the cut part struck through
  • Symbols the rail strips
  • Invoice number moved to the front when it would be cut off
  • Upper-casing on rails that do it

Props

PaymentReference props
PropTypeDefault
label

Visible label.

string"Payment reference"
value

Controlled value.

string—
defaultValue

Initial reference when uncontrolled.

string""
onValueChange

Called with the reference on every change.

(value: string) => void—
pattern

The invoice or order number format the payee matches on.

RegExp/INV-\d{4}-\d{4}/
formatHint

Human-readable form of `pattern`, e.g. "INV-2026-0142".

string"INV-2026-0142"
expected

The invoice this payment is for, when known. Enables one-tap fixes.

string—
rails

Payment rails to offer, with their limits.

PaymentRail[]DEFAULT_RAILS
rail

Controlled rail id.

string—
defaultRail

Initial rail id when uncontrolled.

string—
onRailChange

Called with the chosen rail id.

(id: string) => void—
payerName

Payer name as banks print it, for the statement preview.

string"Your name"
messages

Override any issue message.

Partial<Record<ReferenceIssue, (id: string, rail: string) => string>>—

* required. Also accepts the native props of <input> (className, aria-*, data-*…), passed through to it.

Accessibility

  • Visible label; input is described by a polite hint region
  • Rail picker is a labelled radiogroup
  • Icons are aria-hidden

Only what the source does. Test with your own screen reader and content before shipping.

Limitations

  • Rail limits are sensible defaults, not guarantees; banks differ
  • Doesn't send the payment or reconcile it
  • Pattern for invoice numbers comes from your pattern prop

Rules

Rules not yet verified against an official source.

Not verified this round: rail limits (UPI ~50 characters, NEFT remark boxes ~30, Faster Payments 18) are defaults from the code. Check your bank's own limits. Copied components don't update themselves, so re-check after rule changes (see updating a component).

What it stops

Transfer couldn't be matched to the invoice

Also known as

payment reference · remarks · invoice number · neft · upi · imps · narration · bank statement

Field type

Dependencies

Pairs well with