KQ-1865 · TABLE/SPREAD

Table Spread

A deck squared on a felt table that sweeps into a long, even line under the hand: every card the hand passes is left at its slot while the rest ride on beneath it, and a release commits by projection on springs.glide carrying the hand's velocity. Flicking the first card sends a turnover wave down the spread — each card lifting, turning about its long edge in perspective and landing as the front passes, at turnSpeed cards a second — while a hovered card raises its edge on springs.flick and a picked card steps out of the line and flips face up on springs.snap. The cards are real buttons in a roving tabindex: arrows and Home/End move, Enter picks, T turns the spread over and Escape gathers the deck.

KQ-1865 · TABLE/SPREAD

Fernworks card room · pick a card

Drag the deck to the right to spread it, or press Enter. In the spread, arrow keys move between cards, Enter picks a card, T turns the whole spread over and Escape gathers the deck. Flick the first card to the right to turn the spread over.

deck squared · drag it across the felt

Install

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

$ pnpm dlx shadcn@latest add @kinetiq/table-spread

Props

cards
TableSpreadCard[]
default defaultTableSpreadCards
The deck, bottom card first: { id, rank, suit }. Fifteen seeded cards by default.
spacing
number
default 0.4
How much of each card shows in the spread, as a fraction of its width; a narrow table tightens it to fit.
turnSpeed
number
default 22
How fast the turnover wave runs along the spread, in cards per second.
felt
"green" | "navy" | "claret" | "slate" | string
default "green"
The cloth: a preset pigment or any CSS colour.
backColor
string
default a claret pigment
The colour printed on the card backs, any CSS colour.
spread / defaultSpread
boolean
default false
Whether the deck lies spread across the table.
onSpreadChange
(spread: boolean) => void
default —
Fires from the sweep, tap or key that spread or gathered the deck.
faceUp / defaultFaceUp
boolean
default false
Whether the spread lies face up. A host that changes it gets the same wave a flick would.
onFaceUpChange
(faceUp: boolean) => void
default —
Fires when a turnover wave the visitor started has turned the whole spread.
picked / defaultPicked
string | null
default null
The id of the card picked out of the line, or null.
onPickedChange
(id: string | null) => void
default —
Fires from the tap or key that picked a card or put it back.
lift
number
default 6
How far a hovered card's edge rises, px.
intro
boolean
default false
Spread the deck by itself the first time it comes into view, silently.
label
string
default "Deck of cards"
The table's accessible name.
sound
boolean
default false
Paper sounds for the sweep, each card the wave lands and the pick.
disabled
boolean
default false
Shows the table as it is; nothing sweeps, turns or picks.
className
string
default "h-56"
Size the table with a height class; the cards follow its height and the spacing tightens to fit its width.