# Seat Map

Seat picker for cinemas, cabins and arenas, built from your own seating data. Picked seats light up and settle, and trying to pick more than the limit briefly flickers the seat.

> Composed · Pro · Forms & Inputs — React Native, Expo Go compatible.

## Install

```bash
npx @lumioui/cli add pro/seat-map
```

## Import

```tsx
import { SeatSections, SeatMap } from "@/components/ui/seat-map/seat-map";
```

## Variants

- `cinema` — Cinema: `npx @lumioui/cli add pro/seat-map-cinema`
- `flight` — Flight cabin: `npx @lumioui/cli add pro/seat-map-flight`
- `stadium-sections` — Stadium sections: `npx @lumioui/cli add pro/seat-map-stadium-sections`

## Props

### SeatMap

| Prop | Type | Notes |
| --- | --- | --- |
| `rows` | `SeatRow[]` | Rows top to bottom. |
| `tiers?` | `SeatTier[]` | Price tiers for tint, legend and totals. |
| `value?` | `string[]` | Controlled selected seat ids. |
| `defaultValue?` | `string[]` | Uncontrolled initial selection. |
| `onValueChange?` | `(ids: string[], detail: SeatSelectionDetail) => void` | Fires with the new ids plus the resolved seats and price total. |
| `maxSeats?` | `number` | Maximum seats. Past it the map shakes; with 1, a new pick replaces the old one. Default 8. |
| `onMaxReached?` | `() => void` | Fires when a pick is refused by `maxSeats`. |
| `shape?` | `"chair" | "cabin" | "square"` | Seat silhouette: `chair` (cinema/theatre), `cabin` (aircraft, with headrest), `square` (coach/bus). Default "chair". |
| `screen?` | `string` | Draws a curved screen/stage line above the rows with this label ("Screen"). |
| `columnLabels?` | `(string | null)[]` | Column letters above the grid, one per cell (use `null` for aisle columns) — the aircraft "A B C  D E F" header. |
| `showRowLabels?` | `boolean` | Show row labels in both gutters. Default true when rows have labels. |
| `showLegend?` | `boolean` | Show the legend below the grid. Default true. |
| `maxSeatSize?` | `number` | Largest seat edge in pt; seats shrink to fit narrower columns. Default 30. |
| `gap?` | `number` | Gap between seats in pt. Default 6. |
| `formatPrice?` | `(price: number) => string` | Price formatter for the legend. Default `$18`. |
| `disabled?` | `boolean` | Freeze the map (e.g. while holding seats). |
| `sheen?` | `number` | Bump (e.g. increment) to seal the picks: one sheen crosses them in order. |
| `className?` | `string` | — |

### SeatSections

| Prop | Type | Notes |
| --- | --- | --- |
| `sections` | `SeatSection[]` | — |
| `stage?` | `{ label: string` | Stage / pitch / court block in the same normalised space. |
| `x` | `number` | — |
| `y` | `number` | — |
| `w` | `number` | — |
| `h` | `number` | — |
| `round?` | `boolean }` | — |
| `tiers?` | `SeatTier[]` | — |
| `value?` | `string | null` | Controlled selected section id. |
| `defaultValue?` | `string | null` | Uncontrolled initial section. |
| `onValueChange?` | `(id: string | null, section: SeatSection | null) => void` | Fires with the picked section (or null when tapped again). |
| `aspectRatio?` | `number` | Venue width / height. Default 1. |
| `showLegend?` | `boolean` | Show the tier legend. Default true. |
| `formatPrice?` | `(price: number) => string` | — |
| `className?` | `string` | — |

Source: https://lumioui.com/components/seat-map