KQ-1452 · HARP/STRINGS

Harp Strings

A background of horizontal strings that ring: each is a real fixed–fixed string solved by up to eight standing-wave modes, each turning at its own frequency and fading at its own rate, so a pluck is exact superposition and dies away the way a string does, treble strings shivering faster than bass ones and brightening toward their colour as they ring. A passing pointer catches the nearest string, bends it 1:1 round the hand and lets it go when the hand pushes through, so a slow pass drags each string before it twangs and a fast strum sweeps every one it crosses; a press grabs a string, the drag pulls it 1:1 with rubber-banding and the release plucks it with the hand's speed, and keyboard focus on a control inside strums the strings behind it.

KQ-1452 · HARP/STRINGS

Coldbrook Conservatory

Lessons that ring true

Harp, guitar and voice, all ages

24 strings · a breeze across them

Install

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

$ pnpm dlx shadcn@latest add @kinetiq/harp-strings

Props

children
React.ReactNode
default —
The content on top of the strings: a hero line, a heading, a call to action.
strings
number
default 24
How many strings span the frame, 6 to 48.
damping
number
default 0.35
How quickly a plucked string falls quiet, 0 (rings about four seconds) to 1 (a muted third of a second).
color
"cobalt" | "signal" | "brass" | "rose" | string
default "cobalt"
A ringing string's colour: a named token or any CSS colour.
tension
number
default 0.5
How tight the strings are, 0 (slack, slow and wide) to 1 (tight, a fast shiver).
scale
"pentatonic" | "major" | "minor" | "chromatic"
default "pentatonic"
The notes the strings are tuned to, around C5 in the middle.
breeze
number
default 0.35
How much an idle breeze sets the strings shimmering, 0 to 1.
pluck
number
default 0.6
How hard a passing hand plucks, 0 to 1.
weight
number
default 1.2
A string's line weight, px; bass strings are drawn a little heavier.
inset
number
default 20
How far in from each side the strings are fixed, px.
interactive
boolean
default true
A passing pointer, a press, a drag and keyboard focus inside pluck the strings.
paused
boolean
default false
No breeze; plucked strings still ring.
seed
number
default 1
Seeds the breeze.
dpr
number
default 2
Cap on the canvas's device pixel ratio, at most 2.
sound
boolean
default false
Each pluck plays its string's note. Off unless asked for.
onPluck
(pluck: { string: number; note: string; strength: number }) => void
default —
Fires on every pluck, with the string, its note and how hard.
className
string
default "h-full w-full"
Sizes and shapes the box.