Flight Booking

Flight results

Book your next flight

Compare fares across cabin classes and pick the itinerary that fits.

New York (JFK)London (LHR)
September 30, 2026·1 passenger

Select a flight to continue

About this block

Flight BookingPRO

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.

Booking8: Flight Booking

A single-column flight results card: a header shows the route, date, and passenger count, a three-tab cabin-class selector (economy/business/first) switches every row's displayed fare, each flight row renders airline and flight number, a departure/arrival timeline with a stop marker, baggage and WiFi tags, the price for the active class, and a radio indicator, and a sticky footer summarizes the current pick with a "Book Flight" 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/booking8?email=YOUR_EMAIL&license_key=YOUR_KEY"

Base UI flavor

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

This installs the block to components/beste/block/booking8.tsx, plus the badge, button, and tabs shadcn/ui primitives it uses for the best-value badge, the footer book button, and the cabin-class selector.

Quick start

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

tsx
import { Booking8, booking8Demo } from "@/components/beste/block/booking8";

export default function FlightResultsPage() {
  return <Booking8 {...booking8Demo} />;
}

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

tsx
import { Booking8 } from "@/components/beste/block/booking8";

export default function FlightResultsPage() {
  return (
    <Booking8
      badge={{ label: "Flight results", variant: "secondary" }}
      heading="Book your <strong>next flight</strong>"
      from="New York (JFK)"
      to="London (LHR)"
      date="April 18, 2026"
      passengers={1}
      currency="$"
      flights={[
        {
          legs: [
            {
              departure: "18:30",
              arrival: "06:45",
              departureCode: "JFK",
              arrivalCode: "LHR",
              duration: "7h 15m",
              airline: "British Airways",
              flightNo: "BA 178",
              stops: 0,
            },
          ],
          prices: { economy: 489, business: 1890, first: 4250 },
          baggage: "2 × 23 kg",
          wifi: true,
          bestValue: true,
        },
      ]}
      labels={{
        classLabels: { economy: "Economy", business: "Business", first: "First" },
        directLabel: "Direct",
        bestValueBadge: "Best Value",
        wifiLabel: "WiFi",
        noSelection: "Select a flight to continue",
        bookButton: "Book Flight",
      }}
    />
  );
}

Props

PropTypeDefaultDescription
badge{ label: string; variant?: "default" | "secondary" | "outline" }Section eyebrow badge above the heading
headingstringSection heading, supports inline <strong>
descriptionstringSub-heading paragraph under the heading
fromstringOrigin label shown at the start of the route header
tostringDestination label shown after the arrow
datestringPre-formatted travel date string shown in the header meta row
passengersnumber1Passenger count; toggles the singular/plural label
currencystring"$"Symbol prefixed to every price
flightsFlightOption[][]Flight rows rendered in the list
labelsBooking8Labels{}All display strings for classes, badges, stops, and the footer
classNamestringExtra classes for the outer <section>
ts
type FlightClass = "economy" | "business" | "first";

type FlightLeg = {
  departure: string;
  arrival: string;
  departureCode: string;
  arrivalCode: string;
  duration: string;
  airline: string;
  flightNo: string;
  stops: number;
  stopCity?: string;
};

type FlightOption = {
  legs: FlightLeg[];
  prices: Record<FlightClass, number>;
  baggage: string;
  wifi?: boolean;
  bestValue?: boolean;
};

type Booking8Labels = {
  classLabels?: Partial<Record<FlightClass, string>>;
  passengerSingular?: string;
  passengerPlural?: string;
  bestValueBadge?: string;
  directLabel?: string;
  stopSingular?: string;
  stopPlural?: string;
  wifiLabel?: string;
  noSelection?: string;
  bookButton?: string;
};

Behavior notes

  • The cabin-class tabs use the shadcn Tabs component with a fixed internal list of ["economy", "business", "first"]; labels.classLabels only supplies the visible text, so a class with no label renders a blank tab, and changing the class resets the selected flight back to null.
  • Each row renders only flight.legs[0]; any additional legs in the array are ignored, and a flight whose legs is empty is skipped entirely via an early return null.
  • Selection is tracked by the flight's array index in internal useState, never lifted out, so there is no onSelect or onClassChange callback for the integrator to read the current pick.
  • heading is injected with dangerouslySetInnerHTML, so inline <strong> is bolded and tinted text-primary; pass only trusted markup.
  • The price shown per row and in the footer is flight.prices[selectedClass]; if that class key is missing the row falls back to a literal "—" and the footer prints nothing after the currency symbol.
  • The stop marker dot and the Direct versus "N stops · City" text are derived from leg.stops: 0 shows directLabel, otherwise the count plus stopSingular/stopPlural and an optional · stopCity.
  • The "Book Flight" button is disabled while no flight is selected; clicking it only console.logs the booking payload (route, date, passengers, class, airline, flight number, price), so wiring an actual booking action is left to the integrator.
  • The bestValue badge only appears when both flight.bestValue is true and labels.bestValueBadge is provided; the WiFi tag likewise requires both flight.wifi and labels.wifiLabel.

More Booking blocks

View all Booking
PRO

booking9

Event Ticket Booking

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.

PRO

booking7

Hotel Room Booking

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.

PRO

booking11

Price Calendar

Google Flights-style price calendar with per-day pricing, cheapest day highlights, expensive day indicators, date range selection, and best deal summary banner. Universal for hotels, flights, car rentals, and vacation bookings.

PRO

booking10

Meeting Room Booking

Coworking meeting room reservation with room cards showing capacity, equipment icons, hourly pricing, time range selector, attendee count, and total cost. Office and coworking space booking flow.

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

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.