Cutoff Picker

Counts down to a store's order cutoff in store time with the shopper's time beside it, so an order doesn't land on a different day than expected.

StopsOrder missed today's delivery cutoff

Installation

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

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

Usage

cutoff-picker-usage.tsx
import { CutoffPicker } from "@/components/ui/cutoff-picker"

<CutoffPicker
  storeTimeZone="Asia/Kolkata"
  userTimeZone="America/Los_Angeles"
  cutoff="12:00"
  holidays={holidays}
  now={START + offset + elapsed}
  value={date}
  onValueChange={setDate}
/>

What it catches

  • Store time zone differing from the shopper's (including a different calendar date)
  • Holidays and closed days the delivery date skips
  • A cutoff that passes while the shopper is still choosing
  • Time needed to finish checkout before the cutoff (checkoutMinutes)

Props

CutoffPicker props
PropTypeDefault
storeTimeZone* (required)

IANA zone of the store or warehouse. Cutoffs and dates are the store's.

string—
cutoff

Same-day (or lead-day) cutoff in store time, "HH:MM".

string"14:00"
leadDays

Open days needed after the order day: 0 for same-day, 1 for next-day.

number0
closedWeekdays

Weekdays with no delivery (0 = Sunday).

number[]—
holidays

Store-date holidays with a name to show.

{ date: string; name: string }[]—
days

How many days to offer, starting with the store's today.

number7
value

Selected store date, "YYYY-MM-DD".

string—
defaultValue

Initial date when uncontrolled.

string—
onValueChange

Called with the chosen delivery date.

(date: string) => void—
userTimeZone

Shopper's zone. Defaults to the browser's.

string—
now

"Now" for previews and tests. Defaults to a live clock.

Date | number—
checkoutMinutes

Warn when less than this many minutes are left, since checkout itself takes time.

number5
label

Visible label for the date picker.

string"Delivery date"
countdownText

Templates: `{time}`, `{day}`, `{date}`, `{reason}` and `{yours}` are filled in.

string"Order within {time} for delivery {day}"
cutoffText

Text describing the cutoff time.

string"Cutoff {time} at the store · {yours} for you"
closedText

Text naming skipped holidays and closed days.

string"Today's cutoff has passed. Earliest is {date}{reason}."
hurryText

Text shown when the cutoff is close.

string"Checkout takes a few minutes, so don't wait."
storeDateText

Text shown when the store's date differs from the shopper's.

string"Dates are the store's: it's already {date} there."
rolledText

Text shown when the chosen date is no longer available.

string"{date} closed at {time} while you were choosing."
unavailableText

Text for a date that can't be chosen.

string"{date} isn't available{reason}."
switchLabel

Text for switching to the new earliest date.

string"Switch to {date}"
todayLabel

Word used for today.

string"Today"

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

Accessibility

  • Dates are keyboard-navigable with arrow keys
  • The countdown is a role="img" with an aria-label; the animated digits are aria-hidden
  • Changes are announced in a role="status" region
  • Motion respects prefers-reduced-motion

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

Limitations

This is a UX guard rail. Enforce on the server: Re-check the cutoff on the server at order time and reject or reschedule dates that are no longer available.

  • The cutoff, holidays and closed days come from your props
  • Uses the visitor's clock unless you pass `now`; a wrong device clock skews the countdown

What it stops

Order missed today's delivery cutoff

Also known as

delivery slot · same day delivery · cutoff time · order by · delivery date · blinkit · time slot · store hours

Field type

Dependencies

Pairs well with