Service And Slot PickerPRO

An interactive appointment picker: a hairline panel pairing a selectable service list with a scrollable day strip and a time slot grid that marks unavailable times, beside a full-height provider photo with a gradient name card, closing on a live summary bar and confirm action.

Booking24: Service And Slot Picker

Interactive appointment picker in one hairline panel: a selectable service list on the left, a scrollable day strip over a time slot grid that marks unavailable times in the middle, and a full-height provider photo with a gradient name card on the right, all resolving into a live summary bar and confirm action along the bottom.

Upgrade to Pro

Pro blocks install through the shadcn CLI with your license key and ship their full source. Docs and live previews stay open to everyone, so you can read every block's details first.

Upgrade Now

Installation

Swap YOUR_EMAIL and YOUR_KEY for the email and license key on your account. Find your license key on your account page.

Radix flavor

bash
npx shadcn add "https://ui.beste.co/r/booking24?email=YOUR_EMAIL&license_key=YOUR_KEY"

Base UI flavor

bash
npx shadcn add "https://ui.beste.co/r-base/booking24?email=YOUR_EMAIL&license_key=YOUR_KEY"

This installs the block to components/beste/block/booking24.tsx plus the badge23 and button21 components it uses for the eyebrow and the confirm action.

Quick start

The installed file exports booking24Demo alongside the block: the exact props behind the preview above. Spread it to get a working picker in one line.

tsx
import { Booking24, booking24Demo } from "@/components/beste/block/booking24";

export default function BookingPage() {
  return <Booking24 {...booking24Demo} />;
}

Then replace the demo with your own props. Written out, a trimmed setup looks like this:

tsx
import { Booking24 } from "@/components/beste/block/booking24";

export default function BookingPage() {
  return (
    <Booking24
      badge={{ label: "Booking" }}
      heading="Pick a time that already works for the room"
      location="Marlowe Street clinic, ground floor"
      provider={{
        image: { src: "/images/priya.jpg", alt: "Portrait of Priya Anand" },
        name: "Priya Anand",
        role: "Lead clinician, intake and care plans",
        note: "Usually replies before the next working day",
      }}
      services={[
        { name: "First consultation", duration: "50 min", price: "$180" },
        { name: "Follow-up session", duration: "30 min", price: "$110" },
      ]}
      days={[
        {
          weekday: "Mon",
          day: "14",
          label: "Monday, April 14",
          slots: [
            { time: "09:00", available: true },
            { time: "09:45", available: false },
            { time: "10:30", available: true },
          ],
        },
      ]}
      labels={{
        serviceLabel: "Service",
        dateLabel: "Date",
        timeLabel: "Available times",
        emptyLabel: "Choose a day and a time to continue",
        confirmLabel: "Confirm appointment",
      }}
    />
  );
}

Props

PropTypeDefaultDescription
badge{ label: string }Monospace eyebrow above the hairline rule, rendered via Badge23
headingstringSection heading in the left column
descriptionstringSupporting paragraph, right-aligned from md up
locationstringAddress line with a pin icon under the service list
providerProviderPhoto column with the name card over a gradient scrim
servicesService[][]Selectable service rows, the first one starts selected
daysDay[][]Day strip, each day carrying its own slots
labelsBooking24Labels{}Field kickers, empty-state line, and confirm copy, see below
classNamestringExtra classes for the outer <section>
ts
type Service = { name: string; duration: string; price: string };

type Slot = { time: string; available?: boolean };

type Day = {
  weekday: string;
  day: string;
  label: string;
  slots?: Slot[];
};

type Provider = {
  image: { src: string; alt: string };
  name: string;
  role: string;
  note?: string;
};

type Booking24Labels = {
  serviceLabel?: string;
  dateLabel?: string;
  timeLabel?: string;
  emptyLabel?: string;
  confirmLabel?: string;
};

Behavior notes

More Booking blocks

View all Booking
PRO

booking1

Date & Time Picker

Split-panel booking interface with interactive monthly calendar on the left and time slot grid on the right. Features today highlight, disabled dates, selected state, morning/afternoon grouping, and booking summary footer.

PRO

booking26

Minimal Service Picker

A quiet booking picker whose left column lists each service as a single hairline row carrying only its length and price, swapping a sticky panel that floats a live week strip above the chosen service's detail and its book action.

PRO

booking18

Cinema Seat Picker

Interactive seat selection grid for cinemas, theaters, and events. Row/column layout with an aisle gap, tier-based pricing (standard/premium/VIP), occupied seats, a live selection summary, and a legend. Includes screen indicator at the top.

PRO

booking27

Choose Your Clinician

A clinician picker whose hairline list of practitioners, each showing their next opening, swaps an image tile floating a live availability card alongside their focus, background, and sites.

FREE

booking5

Provider Picker

Staff/provider selection cards with avatar, name, specialty, star rating, review count, availability badge, experience years, and selected state. Grid layout with "Any Provider" option.

FREE

booking4

Service Selector

Service selection grid with category filter tabs, service cards showing icon, name, description, duration, price, and selected state. Ideal for spa, salon, clinic, and fitness booking flows.