KQ-1228 · PUNCH/CARD

Punch Card

A loyalty card you punch: each press sinks the next printed spot under the die on the flick spring, then cuts a real hole through the card (an SVG mask, so the table and the card's own shadow show through), the card jolts and recovers on recoil, and a paper chad carrying its piece of the print pops toward you and falls away under gravity on an ease-in tween. The final punch lights the reward with a recoil landing and a ring, then the card turns over on the snap spring to its redeem side; Redeem turns it back, and the holes give way to a fresh card at the instant it is edge-on. The count is a role="meter" and the punch is a real button, so Space or Enter presses and cuts through the same path, and focus follows the card when it turns.

KQ-1228 · PUNCH/CARD

Coldbrook Coffee

Loyalty · No. 0417

Ari Lund

Nine punches, one free

6 of 9 punched, 3 to go.

Space or Enter punches the next spot.

6 of 9 punched · 3 to the free one

Install

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

$ pnpm dlx shadcn@latest add @kinetiq/punch-card

Props

brand
string
default —
The café or shop, printed on the card's band.
reward
string
default "One free drink"
What a full card is worth.
member
string
default —
The holder's name, printed at the foot of the card.
number
string
default —
The card's number, printed on the band.
code
string
default —
The redeem code on the back. Defaults to a deterministic code from the brand, the member and the cycle.
label
string
default —
The card's accessible name. Defaults to "{brand} loyalty card".
value / defaultValue
number
default 0
How many spots are punched, 0 to holes; controlled or uncontrolled.
onValueChange
(value: number) => void
default —
Fires from the press that punched a spot, or from Redeem with 0.
onRedeem
() => void
default —
Fires when the reward is redeemed.
holes
number
default 9
How many punches earn the reward, 6 to 12; the grid re-lays out in two rows.
shape
"round" | "star" | "heart"
default "round"
The printed spot, the hole and the chad.
chad
boolean
default true
A paper chad pops out of each hole and falls away. Off: a clean cut.
sound
boolean
default false
A click at each cut, rising in pitch across the card, a pop as the reward lights, and a click on Redeem.
disabled
boolean
default false
The card can be read but not punched or redeemed.
className
string
default —
Classes for the root.