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