Xzero UI
Pro library

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
Live · keyboard ready

When to use

When not to use

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.

PropTypeDefaultDescription
venue (required)string–Venue name printed on the ticket.
venueDetailstring–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.
daysnumber21Days on the strip.
timesstring[]["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.
preferredTimestring"19:30"Preselected when free, otherwise the nearest free time, as "HH:MM".
minPartySizenumber1Smallest party.
maxPartySizenumber12Largest party.
defaultPartySizenumber2Starting 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.
hourCycle12 | 2412Clock used for displayed times, such as 7:30 PM or 19:30. times, preferredTime, and onConfirm always use "HH:MM".
labelstring"Book a table"Label of the closed pill.
classNamestring–Class on the root element.

Keyboard interactions

KeysAction
Arrow keysMove a day on the date strip, or between free times in the grid.
Page Up / Page DownMove a week on the date strip.
Home / EndFirst or last day, or first or last free time.
EnterConfirm the date on the strip and continue.
EscapeGo back one step.

Accessibility

Motion

Responsive behavior

Performance

Notes for AI

Also in data

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

Browse all components