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.
A centered booking confirmation card that stacks a service name and description, a muted panel of date/time/duration/location rows, a provider block with avatar and star rating, a promo-code input that validates against a known code, a price breakdown with subtotal/tax/discount/total lines that recomputes the total when a valid promo is applied, a full-width confirm button, and a cancellation-policy footer.
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.
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
npx shadcn add "https://ui.beste.co/r/booking2?email=YOUR_EMAIL&license_key=YOUR_KEY"Base UI flavor
npx shadcn add "https://ui.beste.co/r-base/booking2?email=YOUR_EMAIL&license_key=YOUR_KEY"This installs the block to components/beste/block/booking2.tsx, plus the avatar, badge, and button shadcn/ui primitives it uses for the provider photo, the section eyebrow, and the apply/confirm actions.
The installed file exports booking2Demo alongside the block: the exact props behind the preview above. Spread it to get a working reservation summary in one line.
import { Booking2, booking2Demo } from "@/components/beste/block/booking2";
export default function BookingReviewPage() {
return <Booking2 {...booking2Demo} />;
}Then replace the demo with your own props. Written out, a trimmed setup looks like this:
import { Booking2 } from "@/components/beste/block/booking2";
export default function BookingReviewPage() {
return (
<Booking2
badge={{ label: "Almost done", variant: "secondary" }}
heading="Review your <strong>reservation</strong>"
serviceName="Deep Tissue Massage"
date="Saturday, April 18, 2026"
time="14:00"
duration="60 min"
location="Serenity Spa, 42 Wellness Ave"
provider={{ name: "Dr. Emily Carter", role: "Massage Therapist", rating: 4.9, reviews: 127 }}
pricing={[
{ label: "Deep Tissue Massage (60 min)", amount: "$120.00" },
{ label: "Tax", amount: "$10.40", type: "tax" },
{ label: "Total", amount: "$130.40", type: "total" },
]}
validPromoCode="123456"
promoDiscount={{ label: "Promo code ({code})", amount: "-$20.00" }}
labels={{ applyButton: "Apply", confirmButton: "Confirm Booking" }}
/>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
badge | { label: string; variant?: "default" | "secondary" | "outline" } | – | Centered eyebrow badge above the heading |
heading | string | – | Section heading, supports inline <strong> |
description | string | – | Muted subheading under the heading |
serviceName | string | – | Bold service title at the top of the card |
serviceDescription | string | – | Muted line under the service name |
date | string | – | Date row with a calendar icon |
time | string | – | Time row with a clock icon |
duration | string | – | Appended to the time row after a · separator |
location | string | – | Location row with a map-pin icon |
provider | Provider | – | Provider block with avatar, role, and rating |
pricing | PriceItem[] | [] | Line items in the price breakdown |
cancellationPolicy | string | – | Footer policy text with a shield icon |
validPromoCode | string | – | Code the promo input is compared against |
promoDiscount | PromoDiscount | – | Discount line inserted when the code matches |
labels | Booking2Labels | {} | Copy for the promo input, buttons, and messages |
className | string | – | Extra classes for the outer <section> |
type Provider = {
name: string;
role: string;
avatar?: string;
rating?: number;
reviews?: number;
};
type PriceItem = {
label: string;
amount: string;
type?: "regular" | "discount" | "tax" | "total";
};
type PromoDiscount = {
label: string;
amount: string;
};
type Booking2Labels = {
promoPlaceholder?: string;
applyButton?: string;
appliedButton?: string;
confirmButton?: string;
reviewsSuffix?: string;
promoSuccessMessage?: string;
promoInvalidMessage?: string;
};validPromoCode; there is no async call and no callback, so a real coupon check must be wired in by the integrator.useMemo: it pulls the type: "total" row out, appends the promoDiscount line, then re-adds a total whose amount is re-derived by parseAmount/formatAmount (a naive regex that reads the first number and reuses the currency symbol from the original total string).pricing has no type: "total" item, the promo line is simply appended and nothing is recalculated.useState ("idle" \| "valid" \| "invalid") that is never lifted out; the Apply button is disabled while the input is empty or the code is already valid, and typing resets the status back to "idle".promoInvalidMessage and promoDiscount.label substitute {code} with validPromoCode at render time, so the invalid message can leak the working code (the demo does this on purpose).heading is rendered through dangerouslySetInnerHTML, and its inline <strong> is auto-styled bold and text-primary.onClick handler at all: it is a decorative CTA, so submitting the reservation is left entirely to the integrator.serviceName, provider, pricing, cancellationPolicy, or the whole badge/heading/description header collapses that region without leaving empty spacing.Wiring the form up
This block ships the form markup only; state, validation, and submit are yours to add. Our guide wires the shadcn Field primitives to React Hook Form, TanStack Form, and Formisch on one field system.
booking7
Hotel room selection with room type cards showing images, amenity icons, guest capacity, price per night, check-in/check-out date picker, guest counter, and total price summary.
booking3
Upcoming and past appointments list grouped by date, with service name, provider avatar, time, duration, status badges (confirmed/pending/cancelled), and reschedule/cancel action buttons.
booking15
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.
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.
booking9
Event ticket selection with event banner, date/venue info, ticket tier cards (General/VIP/Backstage) with perks list, quantity selector, and order total. Concert and conference ticket flow.
booking14
Tours and experiences booking card with hero image overlay, rating, duration, difficulty badge, date picker, traveler counter, language selector, highlights list, and reserve CTA. Perfect for guided tours, classes, and local experiences.