Passenger Name Input

Checks a flight or train passenger name against the ID and reads it back as it will print, so a name mismatch doesn't cost a fee or a boarding.

StopsBoarding denied over a ticket name

Installation

pnpm dlx shadcn@latest add https://bollard-ui.vercel.app/r/passenger-name-input.json

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

Usage

passenger-name-input-usage.tsx
import { PassengerNameInput, type IdName, type PassengerName } from "@/components/ui/passenger-name-input"

<PassengerNameInput key={pick.id} value={name} onValueChange={setName} idName={pick.idName} singleNameFormat={pick.format} messages={{ legend: "Adult 1 · as on passport" }} />

What it catches

  • Given name and surname swapped
  • Middle name on the ID missing from the booking
  • Title, suffix or nickname typed into a name field
  • Single-name passengers, ticketed as repeat (JONES/JONES) or FNU
  • Accents or characters the ticket can't print, and names over maxLength

Props

PassengerNameInput props
PropTypeDefault
value

Controlled name.

PassengerName—
defaultValue

Initial name when uncontrolled.

PassengerName{ title: "", given: "", surname: "" }
onValueChange

Called with the whole name whenever any part changes. Nothing is rewritten without a tap.

(value: PassengerName) => void—
idName

The name exactly as on the passport or ID, when you have it (saved profile, scanned MRZ). Turns guesses into exact fixes.

IdName | null—
singleNameFormat

How a single-name passenger is ticketed: "repeat" (IndiGo: LAKSHMI/LAKSHMI) or "fnu" (IATA AIRIMP, needed for US and Canada: LAKSHMI/FNU).

"repeat" | "fnu""repeat"
middleNames

"optional" stops asking for middle names that are on the ID (Air India domestic, for example). Default "required".

"required" | "optional""required"
maxLength

Longest printed name the airline takes, title included.

number59
titles

Titles offered in the title box.

string[]PASSENGER_TITLES
onIssuesChange

Called whenever the list of open issues changes, to gate the Continue button.

(issues: PassengerIssue[]) => void—
delay

Pause in ms after typing before issues appear. Leaving a field shows them at once.

number600
messages

Any visible string; `issues` and `fixes` may be partial.

Partial<Omit<PassengerNameMessages, "issues" | "fixes">> & { issues?: Partial<PassengerNameMessages["issues"]>; fixes?: PassengerNameMess…—

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

Accessibility

  • Title and name inputs have visible labels and are described by the hint and issues
  • Fix buttons are disabled while the result is stale
  • Focus moves to the next fix or the given-name field after a fix

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

Limitations

  • Airline rules differ; defaults follow the airlines named in the code and should be checked for yours
  • Comparison with the ID only works when you pass idName
  • Doesn't change a booking already made

Rules

Rules not yet verified against an official source.

Not verified this round: airline single-name conventions (IndiGo, Air India, IATA AIRIMP FNU) and length limits come from the code's comments. Check with the airline. Copied components don't update themselves, so re-check after rule changes (see updating a component).

What it stops

Boarding denied over a ticket name

Also known as

passenger details · flight booking · irctc · train ticket · name as on id · traveller name · pnr · airline

Field type

Dependencies

Pairs well with