KQ-1769 · SEAT/PLANNER

Seat Planner

A seat management panel where every seat is a chair in a row: seated members sit on theirs as initials on a disc, empty paid seats are outlines and seats added in the draft are dashed accent chairs until confirmed. Adding a seat sets a new chair into the row from 16px above, landing on springs.recoil while its shadow spreads, a cascade apart when several arrive at once, and today's prorated charge rolls up; removing one lifts the chair away on the exit ease and opens the credit on springs.glide. Waiting members drag 1:1 onto an empty chair or seat through a menu; the chairs are one roving group (Left, Right, Home, End, Enter opens a chair's menu) and the count is a spinbutton driven by the arrow and Page keys that never falls below the seats in use.

KQ-1769 · SEAT/PLANNER

Seats

Coldbrook · $12.00 a seat a month

8 of 10 taken

Waiting for a seat · 3

Drag someone onto an empty chair, or open a chair to choose.

Seats

Today

$0.00 today

No change to pay · 15 days left

From Nov 110 seats · $120.00/mo

10 seats · 8 taken · no changes

Install

One command — the source lands in your repo. Or copy it from the Code tab.

$ pnpm dlx shadcn@latest add @kinetiq/seat-planner

Props

seats
number
default 10
Seats paid for today.
value / defaultValue
number
default — / seats
The draft seat count, controlled or initial; the planner follows a controlled value whenever it changes.
onSeatsChange
(count) => void
default —
Fires from the stepper, a key or a menu with the new draft count.
members
SeatMember[]
default defaultSeatMembers
Everyone in the workspace: { id, name, role?, seated }.
onAssign
(memberId, chair | null) => void
default —
Fires when someone is seated (with the chair's index) or stood up (null).
pricing
SeatPricing
default defaultSeatPricing
Price per seat and the billing period: { perSeat, periodStart, periodEnd }.
now
number
default Oct 17 2026, 14:00 UTC
The moment proration counts from, in ms.
maxSeats
number
default 40
The most seats the plan allows.
onConfirm
(change) => void | Promise
default —
Confirm was pressed with { seats, added, removed, charge, credit, assignments }; a rejection keeps the draft and shows its message.
onDiscard
() => void
default —
The draft was thrown away.
workspace
string
default "Coldbrook"
The workspace's name.
status
"ready" | "loading" | "error"
default "ready"
Whether the seats have arrived.
onRetry
() => void
default —
Try again was pressed after the seats failed to load.
chairStyle
"chair" | "stool" | "dot"
default "chair"
How each seat is drawn.
gap
number
default 10
Space between chairs, in px.
accent
"cobalt" | "plum" | "mint" | "ink" | string
default "cobalt"
New chairs, the drop target and Confirm: a named pigment or any CSS colour.
formatMoney
(amount) => string
default Intl USD
How money is written.
disabled
boolean
default false
Seats and assignments are read-only.
className
string
default —
Classes for the panel; it caps at 36rem tall and scrolls inside past that.