Skip to content
Sign in
Generative UIFlight cardMenu

Flight card

A flight option from a travel agent: carrier, times and airports on a drawn route line with the kit's square marks, stops with their layovers, then price, cabin, bags and one select action. Return trips stack their legs.

Two legs on drawn route lines, a connection in Newark, bags and seats left. Open Details for every flight and layover.

Installation

$ pnpm dlx shadcn@latest add https://chatcn.dev/r/flight-card.json

Usage

tsx
import { FlightCard } from "@/components/ui/chatcn/flight-card"

<FlightCard
  legs={[
    {
      carrier: "TAP Air Portugal",
      logo: <img src={carrierLogo} alt="" />,
      departure: { code: "LIS", city: "Lisbon", time: "07:15" },
      arrival: { code: "SFO", city: "San Francisco", time: "14:40" },
      duration: 1045,
      stops: [{ code: "EWR", city: "Newark", duration: 105 }],
    },
  ]}
  price={1184}
  currency="EUR"
  cabin="Economy"
  baggage={{ carryOn: 1, checked: 1 }}
  onSelect={() => choose(offer.id)}
/>

Every widget takes plain props from a tool result, so map the tool output straight onto it. While the call runs, pass loading for a skeleton that matches the final layout; when it fails, pass error (and onRetry). Install with flight-card and nothing else from the kit is required at runtime.

Times are passed already formatted in each airport's local time, the way fare APIs return them; dayOffset adds the +1. The carrier is always text. Logos are yours to supply through logo: the kit ships no airline marks.

The route line

Solid squares mark departure and arrival, hollow squares mark stops. A stop shorter than shortConnection (60 minutes by default), overnight, or with an airport change turns amber and says why, here and in the details.

Examples

Compact options

Three one-way options as rows, with Cheapest and Fastest, and one selected.

States

Loading, an expired fare, no flights, and an overnight layover with a short connection.

Props

PropTypeNotes
legsFlightLeg[]carrier, logo?, label?, date?, departure, arrival, duration, stops?, segments?
FlightPlace{ code, time, city?, airport?, terminal?, dayOffset? }
FlightStop{ code, duration, city?, overnight?, airportChange? }Layover in minutes
segmentsFlightSegment[]Each flight for the Details view
price, currency, locale, priceNoteRound trip, 1 adult
cabin, fareNamestringEconomy, Classic
baggage{ carryOn?, checked? }Reads 1 checked bag, Carry-on only or No bags included
seatsLeftnumberAmber note
badgestringCheapest, Fastest
shortConnectionnumberMinutes. Default 60
selected, onSelect, selectLabelSelected adds an accent outline
layout"full" | "compact"Default full
loading, error, onRetry, emptyStates
labelsPartial<FlightCardLabels>Every string the card shows or announces, durations and the spoken leg included, for translation

Accessibility

  • Each leg is read as one sentence: carrier, departure, arrival with any extra day, duration in words and the stops. The drawn line is hidden from screen readers.
  • Select is a toggle with aria-pressed. Details is a disclosure.
  • Route lines follow the page direction in RTL; times and codes stay in reading order.

Motion

  • Details opens by height and opacity in 200 ms, instantly under reduced motion.
  • Selecting swaps the label to a check with the kit's 150 ms blur crossfade.