KQ-1541 · TAFFY/PULL

Taffy Pull

A display headline whose every letter can be grabbed and pulled like taffy: the part you hold follows the finger 1:1 while the letter's far side stays in its slot, so it stretches along the pull and thins into a neck (redrawn as a textured canvas mesh), rubber-banding past its reach while its neighbours are dragged a little after it on springs.snap. Let go and it snaps home on a spring of the given stiffness that takes the release velocity, while a wobble runs down the word letter by letter on the cascade; fling it hard, or pull far past the reach, and it tears free, arcs out under gravity, and is reeled back into its slot on springs.glide, landing with a recoil. Keyboard: Left and Right choose a letter, Up and Down tug it (Shift with Left or Right tugs sideways), holding the key pulls further and letting go lets it snap.

KQ-1541 · TAFFY/PULL

Fernworks Sweets

Saltwater taffy

Left and right arrows choose a letter. Up and down tug it; Shift with left or right tugs it sideways. Hold a key to pull further, let go to let it snap back.

Pulled by hand in Coldbrook since 1931.

grab a letter · and pull

Install

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

$ pnpm dlx shadcn@latest add @kinetiq/taffy-pull

Props

text
string
default "Pull me"
The headline. Every letter (grapheme) can be pulled; words never break mid-word.
as
"h1" | "h2" | "h3" | "p" | "div" | "span"
default "h2"
The element the headline renders as.
stretch
number
default 0.5
How far a letter reaches before it resists (and, at 1.6× that, tears): 0 is 0.4 of a letter's height, 1 is 1.6.
stiffness
number
default 420
How hard a letter snaps home, as a spring stiffness (120 to 900).
thinning
number
default 0.6
How thin the neck gets as it stretches, 0 to 1.
wobble
number
default 0.5
How long a letter rings after the snap, 0 (dead) to 1 (ringing): the snap spring's damping ratio runs 0.9 to 0.18.
cling
number
default 0.35
How much the neighbours are dragged after a pulled letter, and how far the wobble carries down the word, 0 to 1.
tear
boolean
default true
A hard fling, or a pull far past the reach, tears the letter free; it arcs out and is reeled back.
tearSpeed
number
default 1600
Release speed that tears a letter free, px a second (with at least 40% of the reach pulled).
color
string
default —
Ink for the letters; inherits the text colour unless set.
onPull
(index: number, amount: number) => void
default —
Fires while a letter is pulled, with its index and how far toward the reach it is, 0 to 1 in steps of 0.01.
onSnap
(index: number) => void
default —
Fires when a pulled letter is let go and snaps home, or lands after a tear.
onTear
(index: number) => void
default —
Fires when a letter tears free.
sound
boolean
default false
A twang at the snap pitched by the stretch, a higher one at a tear, a low one at the landing.
disabled
boolean
default false
Letters cannot be pulled; the headline is plain text.
dpr
number
default 2
Cap on the canvas's device pixel ratio, at most 2.
className
string
default —
Sizes the type (set the font size here, the letters inherit it) and places the headline; the box keeps 0.75em above and below for pulls.