Car Rental Booking

Car rental

Rent the right ride

Pickup and return anywhere, upfront pricing, and free cancellation up to 24 hours before your trip.

Pickup
Return
Rental dates
Car class
Insurance

Liability only

+$0 / day
Add-ons
Total$0
About this block

Car Rental BookingPRO

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.

Booking20: Car Rental Booking

A single-card vehicle rental configurator that stacks pickup and return location selects (with a "same location" checkbox that mirrors and disables the return field), a range calendar in a popover, a selectable list of car-class cards showing image, seat and bag counts, transmission, fuel, and per-day price, a tabbed insurance tier selector, a checkbox grid of add-ons, and a live subtotal-plus-total breakdown that recomputes from the selected day count on every change.

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

Base UI flavor

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

This installs the block to components/beste/block/booking20.tsx, plus the badge, button, calendar, checkbox, popover, select, and tabs shadcn/ui primitives it uses for the popular/day badges, the reserve button, the date-range picker, the location and add-on toggles, the dates popover, the location dropdowns, and the insurance tier tabs.

Quick start

The installed file exports booking20Demo alongside the block: the exact props behind the preview above. Spread it to get a working car rental configurator in one line.

tsx
import { Booking20, booking20Demo } from "@/components/beste/block/booking20";

export default function Page() {
  return <Booking20 {...booking20Demo} />;
}

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

tsx
import { Booking20 } from "@/components/beste/block/booking20";

export default function Page() {
  return (
    <Booking20
      badge={{ label: "Car rental", variant: "secondary" }}
      heading="Rent the <strong>right ride</strong>"
      currency="$"
      locations={[
        { value: "sfo", label: "San Francisco Airport (SFO)" },
        { value: "lax", label: "Los Angeles Airport (LAX)" },
      ]}
      defaultPickupLocation="sfo"
      defaultReturnLocation="sfo"
      carClasses={[
        {
          value: "suv",
          label: "Mid-size SUV",
          example: "Honda CR-V or similar",
          image: "/cars/crv.jpg",
          seats: 5,
          bags: 4,
          transmission: "Automatic",
          fuel: "Hybrid",
          pricePerDay: 68,
          popular: true,
        },
      ]}
      insuranceTiers={[
        { value: "basic", label: "Basic", description: "Liability only", pricePerDay: 0 },
      ]}
      addOns={[{ value: "gps", label: "GPS navigation", pricePerDay: 6 }]}
      labels={{ bookButton: "Reserve car", perDayLabel: "/ day", totalLabel: "Total" }}
    />
  );
}

Props

PropTypeDefaultDescription
badge{ label: string; variant?: "default" | "secondary" | "outline" }Optional eyebrow badge above the heading
headingstringSection heading, supports inline <strong>
descriptionstringLead paragraph under the heading
currencystring"$"Symbol prefixed to every price
locationsRentalLocation[][]Options for the pickup and return selects
defaultPickupLocationstring""Initial pickup location value
defaultReturnLocationstring""Initial return location value (used only when "same location" is off)
carClassesCarClass[][]Selectable vehicle cards
insuranceTiersInsuranceTier[][]Tabs for the insurance selector
addOnsRentalAddOn[][]Optional per-day extras in the checkbox grid
labelsBooking20Labels{}All field labels, placeholders, and button copy
classNamestringExtra classes for the outer <section>
ts
type RentalLocation = {
  value: string;
  label: string;
};

type CarClass = {
  value: string;
  label: string;
  example: string;
  image: string;
  seats: number;
  bags: number;
  transmission: string;
  fuel: string;
  pricePerDay: number;
  popular?: boolean;
};

type InsuranceTier = {
  value: string;
  label: string;
  description: string;
  pricePerDay: number;
};

type RentalAddOn = {
  value: string;
  label: string;
  pricePerDay: number;
};

type Booking20Labels = {
  pickupLocationLabel?: string;
  pickupLocationPlaceholder?: string;
  returnLocationLabel?: string;
  sameLocationLabel?: string;
  datesLabel?: string;
  datesPlaceholder?: string;
  carClassLabel?: string;
  insuranceLabel?: string;
  addOnsLabel?: string;
  popularBadge?: string;
  daysLabel?: string;
  perDayLabel?: string;
  totalLabel?: string;
  bookButton?: string;
};

Behavior notes

  • Every selection lives in local useState that is never lifted out: pickup and return location, the "same location" flag (defaults to true), the DateRange, the chosen car class, the insurance tier, and a Set of selected add-on values. There are no onChange callbacks, so the only way to observe state is the internal booking handler.
  • The initial car class is carClasses.find((c) => c.popular)?.value, falling back to the first entry, and the initial insurance is simply the first tier; both fall back to "" when their arrays are empty.
  • totalDays is derived from the date range as Math.max(1, round(diffMs / 86400000)), so a same-day pick still counts as one day, and every subtotal and the grand total are pricePerDay * totalDays. Add-ons sum their per-day prices first, then multiply by the day count.
  • When "same location" is checked, the return Select is disabled and its value mirrors pickupLocation; the separate returnLocation state is only consulted when the box is unchecked.
  • The reserve button is disabled until a car class exists and totalDays > 0; clicking it only calls console.log("Car rental booking:", ...), so persisting or advancing the flow is left to the integrator.
  • heading is injected with dangerouslySetInnerHTML, and its inline <strong> is styled bold and text-primary; pass only trusted markup.
  • The car-class images are plain <img> tags pointing at whatever image URL you supply, the calendar disables any day before today's midnight, and each of the four sections (car classes, insurance, add-ons) only renders when its array is non-empty.
  • Subtotal rows in the footer are conditional: the car row shows only with an active car and days, the insurance row only when its subtotal is above zero, and the add-ons row only when at least one add-on is selected for a priced range.

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

booking18

Cinema Seat Picker

Interactive seat selection grid for cinemas, theaters, and events. Row/column layout with an aisle gap, tier-based pricing (standard/premium/VIP), occupied seats, a live selection summary, and a legend. Includes screen indicator at the top.

PRO

booking17

Ride Booking

Ride-share style booking with pickup/dropoff address inputs, schedule now/later toggle, ride class selector (economy/comfort/xl) with ETA and fare, payment method row, and confirm ride CTA. Perfect for taxi, transfer, and shuttle apps.

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.

FREE

booking4

Service Selector

Service selection grid with category filter tabs, service cards showing icon, name, description, duration, price, and selected state. Ideal for spa, salon, clinic, and fitness booking flows.

PRO

booking23

Cancellation Flow

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.

PRO

booking1

Date & Time Picker

Split-panel booking interface with interactive monthly calendar on the left and time slot grid on the right. Features today highlight, disabled dates, selected state, morning/afternoon grouping, and booking summary footer.