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.
A single-card booking cancellation screen that stacks four sections: the original booking summary (service, provider, confirmation number, date, time, location), a radio list of cancellation reasons each with an optional description plus a free-text notes textarea, a live refund breakdown that computes the refund and processing fee from the booking amount and policy percentage, and a footer with a "this is final" confirmation checkbox gating a destructive cancel button.
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/booking23?email=YOUR_EMAIL&license_key=YOUR_KEY"Base UI flavor
npx shadcn add "https://ui.beste.co/r-base/booking23?email=YOUR_EMAIL&license_key=YOUR_KEY"This installs the block to components/beste/block/booking23.tsx, plus the badge, button, checkbox, and radio-group shadcn/ui primitives it uses for the eyebrow badge, the back/cancel actions, the final-confirmation toggle, and the reason picker.
The installed file exports booking23Demo alongside the block: the exact props behind the preview above. Spread it to get a working cancellation card in one line.
import { Booking23, booking23Demo } from "@/components/beste/block/booking23";
export default function Page() {
return <Booking23 {...booking23Demo} />;
}Then replace the demo with your own props. Written out, a trimmed setup looks like this:
import { Booking23 } from "@/components/beste/block/booking23";
export default function Page() {
return (
<Booking23
badge={{ label: "Cancel booking", variant: "secondary" }}
heading="We're sorry to <strong>see you go</strong>"
currency="$"
booking={{
serviceName: "Deep Tissue Massage",
provider: "Dr. Emily Carter",
date: "Saturday, April 18, 2026",
time: "14:00 to 15:00",
location: "Serenity Spa, 42 Wellness Ave",
confirmationNumber: "BK-2026-0482",
originalAmount: 120,
}}
reasons={[
{ value: "schedule", label: "My plans changed", description: "Something came up" },
{ value: "other", label: "Something else" },
]}
policy={{ refundPercent: 80, description: "Cancelling more than 24 hours out." }}
labels={{ backButton: "Keep booking", confirmButton: "Cancel 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 paragraph below the heading |
currency | string | "$" | Prefix printed before every amount in the refund breakdown |
booking | BookingSummary | – | The booking being cancelled, rendered in the summary section |
reasons | CancellationReason[] | [] | Radio options shown in the reason picker |
policy | RefundPolicy | – | Refund percentage and policy note driving the breakdown |
labels | Booking23Labels | {} | All static UI strings (section headers, buttons, placeholders) |
className | string | – | Extra classes for the outer <section> |
type BookingSummary = {
serviceName: string;
provider: string;
date: string;
time: string;
location: string;
confirmationNumber: string;
originalAmount: number;
};
type CancellationReason = {
value: string;
label: string;
description?: string;
};
type RefundPolicy = {
refundPercent: number;
description: string;
};
type Booking23Labels = {
summaryLabel?: string;
reasonLabel?: string;
notesLabel?: string;
notesPlaceholder?: string;
refundLabel?: string;
originalLabel?: string;
refundedLabel?: string;
feeLabel?: string;
policyLabel?: string;
confirmLabel?: string;
backButton?: string;
confirmButton?: string;
noteTemplate?: string;
};refundAmount is Math.round((originalAmount * refundPercent) / 100) and the processing fee is the remainder (originalAmount - refundAmount), with the fee row labeled by the computed 100 - refundPercent percentage. Both fall back to 0 when booking or policy is absent.canConfirm = Boolean(reason) && confirmed); clicking it only calls console.log("Cancellation confirmed:", ...), so there is no onConfirm callback and wiring the actual cancellation is left to the integrator.backButton) is decorative: it has no onClick handler and does not navigate or reset anything.useState and are never lifted out; the notes textarea value is captured but only surfaced inside the console.log payload.booking, the reason picker needs reasons.length > 0, and the refund breakdown needs both booking and policy; the confirmation/actions footer always renders.heading is injected via dangerouslySetInnerHTML, so inline <strong> is bolded and tinted with text-primary; pass trusted markup only.max-w-xl and does not scroll internally; a long reason list simply grows the page.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.
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.
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.
booking20
Vehicle rental flow with pickup and return location fields, date range picker, car class grid (compact/suv/luxury) with image and specs, insurance tier selector, optional add-ons, and live price breakdown.
booking8
Flight search results with airline logos, departure/arrival times, duration, stops, class selector (economy/business/first), baggage info, and price comparison. Airline ticket booking flow.
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.
booking19
Stepper-based booking flow with numbered progress dots, animated progress bar, and four steps: service selection, schedule, contact details, and review. Back/Next navigation, per-step validation, and a live summary.