Cancellation Flow

Cancel booking

We're sorry to see you go

Review your booking and let us know why you're canceling. We'll refund you based on your cancellation policy.

Booking to cancel

Deep Tissue Massage

Dr. Emily Carter · #BK-2026-0482

Saturday, April 18, 202614:00 — 15:00Serenity Spa, 42 Wellness Ave
Why are you canceling?
Refund summary
Original amount$120
Processing fee (20%)$24
Refund to original method$96
Cancellation policy: You're canceling more than 24 hours before your appointment — you'll receive a partial refund minus the 20% processing fee.

Refund processed in 3–5 business days

About this block

Cancellation FlowPRO

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.

Booking23: Cancellation Flow

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.

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/booking23?email=YOUR_EMAIL&license_key=YOUR_KEY"

Base UI flavor

bash
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.

Quick start

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.

tsx
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:

tsx
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" }}
    />
  );
}

Props

PropTypeDefaultDescription
badge{ label: string; variant?: "default" | "secondary" | "outline" }Centered eyebrow badge above the heading
headingstringSection heading, supports inline <strong>
descriptionstringMuted paragraph below the heading
currencystring"$"Prefix printed before every amount in the refund breakdown
bookingBookingSummaryThe booking being cancelled, rendered in the summary section
reasonsCancellationReason[][]Radio options shown in the reason picker
policyRefundPolicyRefund percentage and policy note driving the breakdown
labelsBooking23Labels{}All static UI strings (section headers, buttons, placeholders)
classNamestringExtra classes for the outer <section>
ts
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;
};

Behavior notes

  • The refund math is derived, not passed in: 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.
  • The cancel button is disabled until a reason is selected and the confirmation checkbox is ticked (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.
  • The "Keep booking" back button (backButton) is decorative: it has no onClick handler and does not navigate or reset anything.
  • Selected reason, notes text, and the confirmation checkbox live in internal useState and are never lifted out; the notes textarea value is captured but only surfaced inside the console.log payload.
  • Each of the three upper sections renders conditionally: the summary needs 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.
  • The whole card is capped at 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.

More Booking blocks

View all Booking
PRO

booking2

Reservation Summary

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.

FREE

booking15

Booking Confirmation Receipt

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.

PRO

booking25

Booking Confirmed

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.

PRO

booking20

Car Rental Booking

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.

PRO

booking8

Flight Booking

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.

PRO

booking6

Restaurant Reservation

Restaurant table reservation with guest count selector, date/time picker, seating preference (indoor/outdoor/bar), special requests textarea, and booking summary. Fine dining reservation flow.