KQ-1134 · SEAT/MAP
Seat Map
A seating chart for one booking: pressing a free seat flips it over on its centre line to its chosen face on the snap spring, with a clack as it lands flat, and the row makes room as its neighbours in the block are kicked aside by a velocity whose target is their own place, so each sways away and back on snap. While picks remain, the free seats beside yours light as together suggestions; taken seats are hatched, and the total rolls digit by digit on glide with a tick. It is a multi-select grid with one tab stop: arrows roam seat by seat over the aisles, Home, End, Ctrl+Home, Ctrl+End, PageUp and PageDown jump, and Space or Enter picks with the same flip and sounds.
Pick up to 4 seats
0 seats$0.00basinworks hall · fri 19:30 · pick up to 4
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/seat-map
Props
- rows
- number
- default 5
- Rows of seats, 1 to 12, lettered from the stage back with I and O skipped. More rows make smaller seats (at most 22px) so the grid stays within about 172px.
- columns
- number
- default 12
- Seats in each row, 4 to 16, numbered from the left.
- aisles
- number
- default 2
- Aisles splitting each row, 0 to 3. Two make the classic short-long-short blocks; otherwise the blocks are even with any spare seats in the middle.
- tiers
- boolean
- default true
- Prices the rows in three bands (front, centre and rear by thirds, the centre taking the remainder), each with its own tint and named in the readout.
- maxPicks
- number
- default 4
- The most seats one booking may hold, 1 to 12. At the limit the other free seats dim and a press is refused with a shrug.
- taken
- string[]
- default []
- Seats already sold, by id (row letter and seat number, "C7"). seatMapId(rowIndex, seatNumber) builds an id the way the map does.
- value / defaultValue
- string[]
- default []
- The chosen seats' ids in the order they were chosen. Ids that are off the map or taken are ignored.
- onValueChange
- (seats: string[]) => void
- default —
- Fires from the press or key that chose or released a seat. A seat flips only once the value that is shown includes it.
- price
- number
- default 36
- Every seat's price when tiers is off.
- tierPrices
- [number, number, number]
- default [48, 36, 24]
- Front, centre and rear prices when tiers is on.
- format
- (amount: number) => string
- default US dollars
- How prices and the total are printed. The total's digits roll; any other characters stay put.
- label
- string
- default "Seats"
- The grid's accessible name.
- stageLabel
- string
- default "Stage"
- Printed under the curve at the top of the map.
- sound
- boolean
- default false
- A clack as a seat lands flat, pitched up with each seat you hold and panned by its column; a softer one as a released seat lands back; a tick as the total rolls; a quiet shrug for a refused seat. Nothing plays, and no audio context exists, unless this is on.
- disabled
- boolean
- default false
- Dims the map and blocks picks; no seat takes focus.
- className
- string
- default —
- Merged onto the wrapper, whose max width is set from the seat size so the footer lines up with the grid.
| Prop | Type | Default | Description |
|---|---|---|---|
| rows | number | 5 | Rows of seats, 1 to 12, lettered from the stage back with I and O skipped. More rows make smaller seats (at most 22px) so the grid stays within about 172px. |
| columns | number | 12 | Seats in each row, 4 to 16, numbered from the left. |
| aisles | number | 2 | Aisles splitting each row, 0 to 3. Two make the classic short-long-short blocks; otherwise the blocks are even with any spare seats in the middle. |
| tiers | boolean | true | Prices the rows in three bands (front, centre and rear by thirds, the centre taking the remainder), each with its own tint and named in the readout. |
| maxPicks | number | 4 | The most seats one booking may hold, 1 to 12. At the limit the other free seats dim and a press is refused with a shrug. |
| taken | string[] | [] | Seats already sold, by id (row letter and seat number, "C7"). seatMapId(rowIndex, seatNumber) builds an id the way the map does. |
| value / defaultValue | string[] | [] | The chosen seats' ids in the order they were chosen. Ids that are off the map or taken are ignored. |
| onValueChange | (seats: string[]) => void | — | Fires from the press or key that chose or released a seat. A seat flips only once the value that is shown includes it. |
| price | number | 36 | Every seat's price when tiers is off. |
| tierPrices | [number, number, number] | [48, 36, 24] | Front, centre and rear prices when tiers is on. |
| format | (amount: number) => string | US dollars | How prices and the total are printed. The total's digits roll; any other characters stay put. |
| label | string | "Seats" | The grid's accessible name. |
| stageLabel | string | "Stage" | Printed under the curve at the top of the map. |
| sound | boolean | false | A clack as a seat lands flat, pitched up with each seat you hold and panned by its column; a softer one as a released seat lands back; a tick as the total rolls; a quiet shrug for a refused seat. Nothing plays, and no audio context exists, unless this is on. |
| disabled | boolean | false | Dims the map and blocks picks; no seat takes focus. |
| className | string | — | Merged onto the wrapper, whose max width is set from the seat size so the footer lines up with the grid. |