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.

KQ-1134 · SEAT/MAP
A
B
C
D
E

Pick up to 4 seats

0 seats$0.00

basinworks 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.