Address Check

Checks a shipping address for a missing house number, a postcode that doesn't fit the country or city, and PO boxes, so parcels aren't returned.

StopsParcel returned for bad address

Installation

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

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

Usage

address-check-usage.tsx
import { AddressCheck, type PostcodePlace } from "@/components/ui/address-check"

<AddressCheck
  lookupPostcode={lookup}
  defaultValue={{ country: "IN", line1: "Sai Residency, Baner Road", line2: "", city: "Mumbai", region: "Maharashtra", postcode: "411045" }}
/>

What it catches

  • No flat or house number in the street line
  • Postcodes in the wrong shape for the country, or that fit another country
  • A city that differs from where your postcode lookup places it
  • PO boxes that couriers can't deliver to
  • Postcode formatting fixed to the canonical shape (e.g. SW1A 1AA)

Props

AddressCheck props
PropTypeDefault
value

Controlled address.

Address—
defaultValue

Initial address when uncontrolled.

Partial<Address>—
onValueChange

Called with the whole address on every change.

(value: Address) => void—
lookupPostcode

Looks up where a postcode is. Resolve null when unknown; rejections are ignored.

(country: string, postcode: string, signal: AbortSignal) => Promise<PostcodePlace | null>—
countries

Country codes offered in the picker, from the built-in rules.

string[]Object.keys(COUNTRIES)
line1Label

Labels and placeholders.

string"Flat / house no., building, street"
line1Placeholder

Placeholder for the first address line.

string"B-204, Sai Residency, Baner Road"
line2Label

Label for the second address line.

string"Area, landmark (optional)"
line2Placeholder

Placeholder for the second address line.

string"Near Balewadi High Street"
cityLabel

Label for the city field.

string"City"
labelHeading

Heading above the printed-label readback.

string"Will print as"
noNumberMessage

Messages. `{city}`, `{typed}`, `{postcode}`, `{label}`, `{example}`, `{country}` are filled in.

string"No flat or house number. Couriers may not find the door."
noNumberDismissLabel

Text for dismissing the missing-number warning.

string"It has none"
poBoxMessage

Warning for PO box addresses.

string"Couriers can't deliver to a PO box. Use a street address."
postcodeFixMessage

Message offering the corrected postcode.

string"{label} should be written {fixed}."
otherCountryMessage

Message when the postcode fits another country.

string"That looks like a {country} postcode."
invalidPostcodeMessage

Message when the postcode doesn't fit the country.

string"{label} should be {example}."
cityMismatchMessage

Message when the city doesn't match the postcode.

string"{postcode} is in {city}, not {typed}."
cityMissingMessage

Message when the city is empty but the postcode is known.

string"{postcode} is in {city}."

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

Accessibility

  • Each field has a hint in an aria-live="polite" region
  • Fixes and dismissals are buttons with visible text
  • The highlight animation respects prefers-reduced-motion

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

Limitations

  • Postcode formats are built in per country; it doesn't confirm the address exists
  • The city check needs a lookupPostcode function from you

What it stops

Parcel returned for bad address

Also known as

address · shipping address · delivery address · postcode · zip · checkout · address form · house number

Field type

Dependencies

Pairs well with