KQ-1340 · GIFT/BUILDER

Gift Builder

A gift card you build by looking at it: the amount rolls onto the card's face digit by digit on snap, a design wipes across it as a circle growing on glide from the side its swatch sits on (or slides in 1:1 under your thumb when you swipe the card itself, committing by projection), and writing the message turns the card over on glide — side to side, or top over bottom — while each new run of characters inks onto the back and the type shrinks on glide to fit. Add to bag runs your promise and, when it lands, a paper band wraps across the card on glide and the seal lands on recoil. Amount, design, send day and the card's face are radiogroups, a slider and a toggle with full keyboard paths, and the card turns to follow the fields focus is in.

KQ-1340 · GIFT/BUILDER

Send a gift card

Fernworks · sent by email, never expires

$50

Amount

$50

Write

89/180

We send the card here, with your message.

Deliver

Arrives Thu, Oct 8 · by email.

Meadow · for Maya

$50 · meadow · sends thu oct 8

Install

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

$ pnpm dlx shadcn@latest add @kinetiq/gift-builder

Props

flip
"turn" | "tumble" | "none"
default "turn"
How the card shows its back: turned side to side about the vertical axis, tumbled top over bottom, or laid beside the front with no turning, both faces updating live.
designs
"swatches" | "tiles" | "swipe"
default "swatches"
How a design is picked: round swatches or miniature cards (the new design wipes across from the picker's side), or by swiping the card itself with dots as the radiogroup.
amount
"chips" | "slider"
default "chips"
How the amount is set: preset chips with a sliding pill and a Custom field, or a logarithmic detent slider that is drawn to the presets and settles on its step with the release velocity.
designOptions
GiftDesign[]
default defaultGiftDesigns
The designs on offer: id, name, art (meadow, confetti, linen, night, bloom, tide) and a tint drawn at fixed lightness.
amounts
number[]
default [25, 50, 100, 150]
The preset amounts: chips, or the slider's labelled detents.
min
number
default 10
The smallest amount, for the slider and the custom field.
max
number
default 500
The largest amount.
step
number
default 5
The slider's step; arrows move one, Page keys five.
value / defaultValue
GiftValue
default defaultGiftValue
The gift: amount, design id, to, from, message, recipient email and the send day (YYYY-MM-DD, or null to send now). Controlled or uncontrolled.
onValueChange
(value: GiftValue) => void
default —
Fires from the chip, key, drag, swipe or field that changed the gift.
side / defaultSide
"front" | "back"
default "front"
The face the card shows. Controlled or uncontrolled; ignored when flip is none.
onSideChange
(side: GiftSide) => void
default —
Fires when the visitor moves to the message (back), the amount or design (front), or turns the card with Show back.
onSubmit
(value: GiftValue) => void | Promise<void>
default —
Buy it. A promise holds Add to bag pending with its width kept; reject with an Error to show its message in an alert.
state
"idle" | "pending" | "done" | "error"
default —
Controlled purchase state; done wraps the card and shows the confirmation.
onStateChange
(state: GiftState) => void
default —
Fires as the purchase is asked for, done or refused.
onReset
() => void
default —
Make another was pressed after a purchase.
brand
string
default "Fernworks"
The shop on the card's face, back and seal.
maxMessage
number
default 180
The message's limit; the counter turns warn in the last twenty characters.
scheduleDays
number
default 14
Days ahead a send can be scheduled.
now
number | Date
default defaultGiftNow
The builder's moment: send days count from it, never the wall clock.
formatPrice
(amount: number) => string
default US dollars, whole when whole
Amounts to text, on the card, the chips, the slider and the button.
title
string
default "Send a gift card"
The heading, and the region's name unless label is given.
status
"ready" | "loading" | "error"
default "ready"
Whether the designs have arrived: loading shows skeletons, error a message with Try again.
onRetry
() => void
default —
Try again was pressed after loading failed.
label
string
default —
The region's accessible name, when the visible title is not enough.
sound
boolean
default false
Paper when the visitor turns the card and as the band wraps; a swish when a design arrives or the amount moves.
disabled
boolean
default false
Read only: the card and the answers show, nothing changes.
className
string
default —
Classes for the root. It is at most 560px tall and scrolls inside itself.