Booking pillPro
One pill that reshapes through party size, date, time, and a ticket.
$ pnpm dlx shadcn@4.23.0 add @xzero-ui-pro/booking-pill- Type: Component (special)
- Access: Xzero Pro
- Page: https://ui.xzero.co.uk/components/booking-pill
- Markdown: https://ui.xzero.co.uk/components/booking-pill/markdown
- Source file:
registry/components/booking-pill/booking-pill.tsx - Dependencies: motion, lucide-react
- Keywords: special, motion, react booking widget, table reservation, restaurant booking ui, date and time picker flow, reservation pill, booking flow
When to use
- Venue or service pages where booking a table or slot is the one action people came for.
- Mobile-first flows that walk through party size, date, time, and confirm in one surface.
When not to use
- Use date-picker and time-picker inside a regular form for multi-field checkouts.
- Use stepper or multi-step-form for longer flows with many fields.
- Use calendar when people need to see a whole month.
Installation
Register both Xzero UI namespaces in your project's components.json:
{
"registries": {
"@xzero-ui": "https://mcp.xzero.co.uk/r/{name}.json",
"@xzero-ui-pro": "https://mcp.xzero.co.uk/r/pro/{name}.json"
}
}
npx shadcn@4.23.0 add @xzero-ui-pro/booking-pill
Install xzero-foundation once, and import @/components/xzero/foundation.css in your app root. No Xzero token is used by this snapshot. For sample portraits, photos, fonts, or logos, download https://mcp.xzero.co.uk/install-assets.mjs and run node xzero-install-assets.mjs <receiving-project>.
Usage
import { BookingPill, type Booking } from "@/components/xzero/booking-pill/booking-pill";
export function ReserveBar({ today, book }: { today: string; book: (booking: Booking) => Promise<void> }) {
return (
<BookingPill
venue="Osteria Nove"
venueDetail="12 Harbour Street"
startDate={today}
hourCycle={24}
isAvailable={(date, time, party) => !(party > 6 && time > "20:00")}
onConfirm={book}
/>
);
}
API reference
BookingPill
One floating pill that reshapes itself through a booking flow: party size, a draggable date strip, a time grid, a ticket to confirm, and a booked state.
| Prop | Type | Default | Description |
|---|---|---|---|
venue (required) | string | – | Venue name printed on the ticket. |
venueDetail | string | – | Second ticket line, such as the address. |
startDate (required) | string | – | First day on the strip as an ISO date. Pass it from data so server and client agree. |
days | number | 21 | Days on the strip. |
times | string[] | ["17:00", "17:30", … "22:30"] | Seating times as "HH:MM", in order, shown four to a row. The default runs every half hour from 17:00 to 22:30. |
isAvailable | (date: string, time: string, partySize: number) => boolean | – | Whether a time is free. Everything is free by default. |
preferredTime | string | "19:30" | Preselected when free, otherwise the nearest free time, as "HH:MM". |
minPartySize | number | 1 | Smallest party. |
maxPartySize | number | 12 | Largest party. |
defaultPartySize | number | 2 | Starting party size. |
onConfirm | (booking: { date: string; time: string; partySize: number }) => Promise<void> | void | – | Books the table. Resolve to show the booked state, reject to keep the ticket open with an error. Defaults to a short simulated wait. |
onStepChange | (step: "start" | "party" | "date" | "time" | "review" | "booked") => void | – | Called on every step, for example to let the page recede while the pill is open. |
hourCycle | 12 | 24 | 12 | Clock used for displayed times, such as 7:30 PM or 19:30. times, preferredTime, and onConfirm always use "HH:MM". |
label | string | "Book a table" | Label of the closed pill. |
className | string | – | Class on the root element. |
Keyboard interactions
| Keys | Action |
|---|---|
| Arrow keys | Move a day on the date strip, or between free times in the grid. |
| Page Up / Page Down | Move a week on the date strip. |
| Home / End | First or last day, or first or last free time. |
| Enter | Confirm the date on the strip and continue. |
| Escape | Go back one step. |
Accessibility
- The date strip is a role="slider" with a spoken aria-valuetext; times are a role="radiogroup" with unavailable times marked aria-disabled.
- Every round icon button has an aria-label (Back, Fewer guests, Next, choose a date).
- Step changes are announced in a polite live region, and booking errors use role="alert".
Motion
- The pill's shape springs to fit each step while content slides in a beat later in the direction of travel.
- The date strip follows drags 1:1, rubber-bands at the ends, and flicks glide to a day; party count digits roll.
- Reduced motion jumps the strip, drops slides and blurs, and swaps faces with fades.
Responsive behavior
- The root is a container; each step's face is capped at the container width minus 24px, up to 340 to 420px.
- The date strip drags horizontally with touch-action pan-y, so vertical page scroll still works on touch.
Performance
- The pill uses a 24px backdrop blur; the date strip renders every day in days, 21 by default.
- ResizeObservers track each face for the shape spring, and only the current step is mounted.
Notes for AI
- Use on a venue or service page where booking is the one action people came for. Use date-picker and time-picker in a regular form for multi-field checkouts.
- Anchor it to the bottom of its container, pass startDate from the server, and wire isAvailable and onConfirm to your backend. Set hourCycle for display only; data stays in "HH:MM".
Related
- Date picker: Choose a date without losing context.
- Time picker: Choose a time with sensible keyboard behavior.
- Calendar: Browse dates in a clear, compact month view.
- Number field: Enter a bounded number with clear increment controls.
- Stepper: Show where a person is in a multi-step flow and what is done.
Also in data
- Activity rings: Daily goals as tick rings that sweep, count up, and trace a second lap past 100%.
- Time dial: Spin a dial to pick an hour and see which team cities are at work.
- Date reel: A 3D wheel date and time picker (like iOS reels) with momentum scrolling, snapping, curved perspective, and full keyboard support.
Guidance for AI tools
Booking pill: One pill that reshapes through party size, date, time, and a ticket. Follow the declared prop types and do not invent props. Keep keyboard access, reduced motion support, and both light and dark themes intact when adapting it.
Full library index: https://ui.xzero.co.uk/llms.txt