PIN Code Input

Reads the state from an Indian PIN's first digits as you type and flags a mismatch with the chosen state, so a parcel doesn't go to the wrong place.

StopsParcel sent to the wrong state

Installation

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

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

Usage

pincode-input-usage.tsx
import { PincodeInput, type PinPlace } from "@/components/ui/pincode-input"

<PincodeInput value={pin} onValueChange={setPin} lookup={lookup} state={state} onUseState={setState} city={city} onUseCity={setCity} />

What it catches

  • PIN prefix that doesn't match the chosen state
  • Letter O for 0, and digits from other scripts
  • Wrong length or unused prefixes
  • Army Post Office codes
  • US ZIP or UK postcodes typed for India, with a country switch

Props

PincodeInput props
PropTypeDefault
label

Visible label.

string"PIN code"
value

Controlled code (other-script digits converted, spaces removed for India).

string—
defaultValue

Initial code when uncontrolled.

string""
onValueChange

Called with the cleaned code on every change.

(value: string) => void—
country

ISO country the address is in. India gets full PIN checks; others get a shape check.

string"IN"
onCountryChange

Offered as a one-tap switch when the code looks like it belongs to another country.

(country: string) => void—
state

The state picked elsewhere in the form, checked against the PIN.

string—
onUseState

Lets the user take the PIN's state in one tap.

(state: string) => void—
city

The city typed elsewhere in the form, checked against the lookup.

string—
onUseCity

Lets the user take the PIN's district in one tap.

(city: string) => void—
lookup

Finds where a complete Indian PIN is. Resolve null when no post office has it. See createIndiaPostLookup.

(pin: string, signal: AbortSignal) => Promise<PinPlace | null>—
onPlaceChange

Called with the place once found, or null when the PIN changes or isn't found.

(place: PinPlace | null) => void—
messages

Override any message or label.

Partial<typeof PINCODE_MESSAGES>—

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

Accessibility

  • Visible label; input has aria-invalid when the lookup finds nothing and is described by a polite status
  • Fixes are buttons; focus returns to the input
  • Icons are aria-hidden

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

Limitations

  • Prefix-to-state is a table and can't tell every border case without the lookup
  • Format looks valid is not the same as deliverable
  • Area and city checks need your lookup

Rules

Rules not yet verified against an official source.

Not verified this round: the prefix-to-state table is from India Post via Wikipedia ("Postal Index Number"), not a primary India Post source. Copied components don't update themselves, so re-check after rule changes (see updating a component).

What it stops

Parcel sent to the wrong state

Also known as

pincode · pin code · postal code · zip · india post · shipping address · checkout · delivery

Field type

Dependencies

Pairs well with