Activity Experience Booking

Experiences

Book your next adventure

Small-group tours, hands-on classes, and guided experiences with top-rated local hosts.

Sunrise Hot Air Balloon Ride
4.9(1847)

Sunrise Hot Air Balloon Ride

Cappadocia, Türkiye

3 hours
Duration
Easy
Difficulty
Up to 20
Group
Pick a date
Travelers
Language
What's included
  • Professional pilot with 10+ years experience
  • Panoramic views over the fairy chimneys
  • Complimentary champagne toast after landing
  • Free hotel pickup and drop-off
  • Flight certificate included

Total

$378

$189 per person

About this block

Activity Experience BookingPRO

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.

Booking14: Activity Experience Booking

A single-column experience booking card rendering a hero image with a dark overlay, floating rating badge, and title/location caption, a three-column duration/difficulty/group-size info strip, a horizontally scrollable 14-day date picker that greys out unavailable slots, traveler-count and language Select dropdowns, an optional highlights checklist, and a sticky footer that totals price per person against the traveler count and gates a reserve button on date selection.

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

Base UI flavor

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

This installs the block to components/beste/block/booking14.tsx, plus the badge, button, and select shadcn/ui primitives it uses for the rating/eyebrow badges, the reserve button, and the traveler and language dropdowns.

Quick start

The installed file exports booking14Demo alongside the block: the exact props behind the preview above. Spread it to get a working experience booking card in one line.

tsx
import { Booking14, booking14Demo } from "@/components/beste/block/booking14";

export default function ExperiencePage() {
  return <Booking14 {...booking14Demo} />;
}

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

tsx
import { Booking14 } from "@/components/beste/block/booking14";

export default function ExperiencePage() {
  return (
    <Booking14
      badge={{ label: "Experiences", variant: "secondary" }}
      heading="Book your <strong>next adventure</strong>"
      experienceTitle="Sunrise Hot Air Balloon Ride"
      experienceLocation="Cappadocia, Türkiye"
      experienceImage="/experiences/balloon.jpg"
      rating={4.9}
      reviewCount={1847}
      duration="3 hours"
      difficulty="Easy"
      groupSize="Up to 20"
      currency="$"
      pricePerPerson={189}
      languages={["English", "Spanish", "French"]}
      highlights={["Professional pilot", "Panoramic views", "Hotel pickup"]}
      unavailableDates={["2026-07-15", "2026-07-18"]}
      labels={{ pickDateLabel: "Pick a date", reserveButton: "Reserve experience" }}
    />
  );
}

Props

PropTypeDefaultDescription
badge{ label: string; variant?: "default" | "secondary" | "outline" }–Optional eyebrow badge above the heading
headingstring–Section heading, supports inline <strong>
descriptionstring–Lead paragraph under the heading
experienceTitlestring–Title shown over the hero image and used as the image alt
experienceLocationstring–Location line with pin icon over the hero
experienceImagestring–Hero image URL; the whole hero block is omitted when absent
ratingnumber–Numeric rating in the floating hero badge
reviewCountnumber–Parenthetical review count next to the rating
durationstring–First info pill value (clock icon)
difficultystring–Second info pill value (mountain icon)
groupSizestring–Third info pill value (users icon)
currencystring"$"Currency symbol prefixed to prices
pricePerPersonnumber0Per-person price, multiplied by traveler count for the total
languagesstring[][]Options for the language Select
highlightsstring[][]Checklist items; section hidden when empty
unavailableDatesstring[][]ISO date keys ("2026-07-15") that disable matching date buttons
labelsBooking14Labels{}All static UI strings (see type below)
classNamestring–Extra classes for the outer <section>
ts
type Booking14Labels = {
  todayLabel?: string;
  durationLabel?: string;
  difficultyLabel?: string;
  groupSizeLabel?: string;
  pickDateLabel?: string;
  travelersLabel?: string;
  languageLabel?: string;
  highlightsLabel?: string;
  perPersonLabel?: string;
  totalLabel?: string;
  reserveButton?: string;
  travelerSingular?: string;
  travelerPlural?: string;
};

Behavior notes

  • The date strip is generated at render from new Date(): it always shows the next 14 days starting today, so dates are relative to when the component mounts, not fixed props. A date is disabled only when its computed YYYY-MM-DD key appears in unavailableDates.
  • Selection state (selectedDateIndex, travelers, language) lives entirely in internal useState and is never surfaced through a callback, so the parent cannot read or control the current selection; travelers defaults to 2 and language initializes to languages[0].
  • The traveler dropdown is hardcoded to offer 1 through 20 regardless of the groupSize string, which is display-only text and does not cap the counter.
  • The reserve button is disabled until a date is selected, and handleReserve only calls console.log(...) with the reservation payload, so wiring the actual booking submission is left to the integrator.
  • heading is rendered via dangerouslySetInnerHTML, letting inline <strong> tags render as bold primary-colored text; pass only trusted markup.
  • The footer's date/summary block (weekday, month, day, and the travelers × language line) is conditionally rendered and appears only once a date is selected; the total (pricePerPerson * travelers) updates live with the dropdown.
  • The date row scrolls horizontally with its scrollbar hidden via CSS, and the header cluster (badge, heading, description) is skipped entirely when none of those three props are provided.

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

FREE

booking5

Provider Picker

PRO

booking12

Search Bar Hero

Get Pro access