KQ-1352 · DRUM/WORDS

Drum Words

One word of a sentence on a ratcheted drum: the slot is a window onto a cylinder of faces placed with real 3D transforms about an axis behind the line, so the outgoing word tips away over the top while the next comes up from below foreshortened and shaded. Each change is one detent — a hair backwards on springs.flick as the pawl lifts, then forward on springs.snap, whose single overshoot is the detent catching — and the slot's width follows the word on springs.glide so the sentence glides instead of jumping. The word is a spinbutton: Up/Right, Enter and Space turn it forward, Down/Left back, Home/End to the ends, and a vertical drag turns the drum 1:1 with a throw committing to the detent it was heading for.

KQ-1352 · DRUM/WORDS

Fieldline · maps that work offline

We build maps for
field crews.

turning · 1 of 5 · field crews

Install

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

$ pnpm dlx shadcn@latest add @kinetiq/drum-words

Props

words
string[]
default —
The words on the drum's faces, in turning order.
before
string
default ""
The sentence before the slot; end it with "\n" to set the word on its own line so a longer word never re-wraps the sentence.
after
string
default ""
The sentence after the slot, including any leading space it needs.
as
"h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "p" | "span" | "div"
default "h2"
The element rendered.
index / defaultIndex
number
default 0
The word showing, controlled or initial.
onIndexChange
(index: number) => void
default —
Fires from the turn that changed it — the timer, a key, a tap or a throw — with the new index.
interval
number
default 2400
How long each word rests before the drum turns, ms; 0 turns only by hand.
depth
number
default 0.6
Drum curvature, 0 to 1: 0 is a nearly flat roll, 1 a tight drum with deep foreshortening.
width
"fit" | "widest"
default "fit"
"fit" springs the slot to each word so the sentence glides; "widest" holds the widest word so it never moves.
align
"start" | "center"
default "start"
Where a word sits in a slot wider than it.
color
string
default "var(--accent-bright)"
The words' colour.
pauseOnHover
boolean
default true
Hold the drum while the pointer rests on the word.
paused
boolean
default false
Stop turning on the timer; keys, taps and throws still turn it.
interactive
boolean
default true
The word is a control: drag or throw it vertically, tap it, or use the arrow keys.
trigger
"mount" | "inView" | "hover" | "manual"
default "inView"
When the timer runs: from mount, once seen, only while the sentence is hovered or focused, or never (turn by index).
once
boolean
default false
Turn through the words a single time and rest on the last.
delay
number
default 0
Extra wait before the first turn, ms.
sound
boolean
default false
Tick on every detent the visitor turns; the timer's turns are silent.
onComplete
() => void
default —
Fires when a once cycle comes to rest on the last word.
className
string
default —
Classes for the sentence; set the type size and colour here.