Seat mapPro
A flight or venue seat map the assistant renders in the thread: price tiers, taken seats, exit rows, keyboard navigation that skips aisles, a live readout of the focused seat and a selection summary with a rolling total.
On this page
ProTwo travellers pick seats on a Lisbon to Copenhagen flight, with a rolling total and a seat hold.
Installation
Usage
import { SeatMap } from "@/components/ui/chatcn/pro/seat-map"
<SeatMap
rows={rows}
columns={["A", "B", "C", null, "D", "E", "F"]}
tiers={tiers}
max={2}
value={seats}
onValueChange={setSeats}
onConfirm={holdSeats}
/>Rows hold seats in order from the start edge, with null for an aisle. Each seat names a tier, and tiers carry the price. Tier color shows only as a small headrest mark and in the legend, with the price as words, so the map stays quiet and reads without color.
With max={1} picking another seat swaps. With more, the selection caps at max and the readout says how to make room. holders puts a passenger or guest name next to each picked seat.
Examples
Venue
ProA recital hall with a centre aisle, up to four tickets, accessible seats and a sound desk.
Loading, error, held and RTL
ProThe map loading, failing with a retry, held after confirm and disabled.
Props
| Prop | Type | Notes |
|---|---|---|
rows | SeatRow[] | { id, label, seats: (Seat | null)[], exit? } |
tiers | SeatTier[] | { id, label, price }, colored in order |
layout | "cabin" | "venue" | Fuselage nose or stage edge. Default cabin |
columns | (string | null)[] | Column letters over the cabin |
value, defaultValue, onValueChange | string[] | Controlled or not |
max | number | Default 1, which swaps on pick |
holders | string[] | Names next to each picked seat |
status | "ready" | "loading" | "error" | "holding" | "held" | Default ready |
onConfirm, confirmLabel, heldNote | The hold button and its result | |
onRetry, error | Error copy and retry | |
currency, locale | string | Default EUR, en-GB |
mapHeight | number | Max map height before it scrolls |
disabled | boolean |
Keyboard
| Key | Action |
|---|---|
Tab | Into the map on one seat, then on to the summary |
ArrowLeft, ArrowRight | Previous or next seat in the row, skipping aisles. Flips in RTL |
ArrowUp, ArrowDown | Same column in the next row, or the nearest seat |
Home, End | First or last seat in the row |
Enter, Space | Pick or drop the focused seat |
Accessibility
- A grid of rows with one tab stop. Every seat, taken ones included, is reachable and named with its position, tier, price and status, so people can explore before they pick.
- Picked seats are pressed buttons and selected grid cells. The cap notice is announced politely.
- Taken seats carry a slash and a fill, not only a color. Exit rows carry marks at both ends and say so to screen readers.
Motion
- Seats press to 0.94 and change fill in 150 ms. The total rolls with Number flow. Keyboard moves never animate.
- Reduced motion: the total swaps with a short fade, nothing moves.