Post-booking success screen with animated check icon, confirmation number, booking summary (service, date/time, location, total), scannable QR code ticket, action buttons (calendar, receipt, directions), and email confirmation note.
Post-checkout confirmation screen: an animated success check, a confirmation number, a list of booking details keyed to a fixed icon set, a provider row, a purely decorative but visually authentic QR code generated from the confirmation number, action buttons, and an email and cancellation-policy footer.
Free block
This block is free. No license or account is required: install it with the CLI and use it in unlimited projects.
Radix flavor
npx shadcn add "https://ui.beste.co/r/booking15"Base UI flavor
npx shadcn add "https://ui.beste.co/r-base/booking15"This installs the block to components/beste/block/booking15.tsx, plus the badge and button shadcn/ui primitives it uses for the status badge and the action buttons.
The installed file exports booking15Demo alongside the block: the exact props behind the preview above. Spread it to get a working confirmation receipt in one line.
import { Booking15, booking15Demo } from "@/components/beste/block/booking15";
export default function BookingConfirmedPage() {
return <Booking15 {...booking15Demo} />;
}Then replace the demo with your own props. Written out, a trimmed setup looks like this:
import { CalendarPlus, Navigation } from "lucide-react";
import { Booking15 } from "@/components/beste/block/booking15";
export default function BookingConfirmedPage() {
return (
<Booking15
badge={{ label: "Confirmed", variant: "secondary" }}
heading="You're all <strong>set</strong>"
description="Your booking is confirmed."
confirmationNumber="BK-2026-0482"
details={[
{ key: "service", label: "Service", value: "Deep Tissue Massage", subValue: "60 min session" },
{ key: "date", label: "Date", value: "Thursday, March 5, 2026" },
{ key: "time", label: "Time", value: "14:00 — 15:00" },
{ key: "price", label: "Total paid", value: "$120.40", subValue: "Visa •••• 4242" },
]}
actions={[
{ icon: CalendarPlus, label: "Add to calendar", href: "https://beste.co" },
{ icon: Navigation, label: "Get directions", href: "https://beste.co" },
]}
email="alex@beste.co"
policyNote="Free cancellation up to 24 hours before your appointment."
labels={{
confirmationPrefix: "Confirmation",
scanLabel: "Scan at check-in",
emailSentTemplate: "Confirmation emailed to {email}",
policyLabel: "Cancellation policy",
}}
/>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
badge | { label: string; variant?: "default" | "secondary" | "outline" } | – | Status badge, always shown with a shield-check icon |
heading | string | – | Section heading, supports inline <strong> |
description | string | – | Section intro text |
confirmationNumber | string | – | Shown under the success icon and used to seed the QR pattern |
details | BookingDetail[] | [] | Icon-labeled rows in the details list |
provider | { name: string; title: string; avatar: string } | – | Provider row shown between details and the QR code |
actions | Booking15Action[] | [] | Buttons in the actions grid |
email | string | – | Interpolated into labels.emailSentTemplate for the footer note |
policyNote | string | – | Cancellation policy text in the footer |
labels | Booking15Labels | {} | UI copy: confirmation prefix, scan caption, email template, policy label |
className | string | – | Extra classes for the outer <section> |
type BookingDetail = {
key: "service" | "date" | "time" | "location" | "guest" | "price";
label: string;
value: string;
subValue?: string;
};
type Booking15Action = {
icon: LucideIcon;
label: string;
href?: string;
};
type Booking15Labels = {
confirmationPrefix?: string;
scanLabel?: string;
emailSentTemplate?: string;
policyLabel?: string;
};generateQRPattern seeds a small hash-based pseudo-random generator from confirmationNumber (falling back to "BK-DEMO" when unset) to fill a 21x21 grid, then overlays three genuine QR-style finder squares (7x7 rings with 3x3 cores, with cleared quiet zones around them) purely so it reads as a QR code in a static preview.details[].key must be one of six fixed values (service, date, time, location, guest, price); each maps to a fixed Lucide icon through the internal detailIcons map, so there is no way to attach a custom icon to a detail row.formatFutureDate(4) (today plus four days) inside a factory function, createBooking15Demo(), that runs once when the module is first evaluated, not on every render, so the shipped booking15Demo date is fixed to whenever that module first loaded rather than "four days from the current visitor."<a href> (via asChild) when action.href is set, or a plain non-interactive button when it's omitted; there is no calendar or maps integration built in, only whatever URL the caller supplies.animate-ping overlay on an emerald-tinted circle for the pulse effect, and the whole card is a single scrollable stack of bordered sections (header, details, provider, QR, actions, footer notes) that each render conditionally based on whether their prop is provided.booking25
A confirmation screen with an accent eyebrow, a two-column hairline table of the appointment details, a checked list of what to bring, and a sticky tile floating the live phone view the member also receives.
booking2
Booking confirmation card with service details, date/time, provider info with avatar, price breakdown with subtotal/tax/discount/total, promo code input, cancellation policy, and confirm CTA.
booking23
Booking cancellation screen with the original booking summary, cancellation reason picker (radio list with optional notes), live refund breakdown based on cancellation policy, confirmation checkbox, and destructive cancel action.
booking24
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.