KQ-1611 · BAND/COMPARE

Band Compare

Several versions of one picture side by side as bands across a single frame, in register, each labelled at its top. Drag any seam and it follows 1:1 while only the two bands either side give way, rubber-banding against a neighbour and landing on springs.glide with the release velocity; the grip lifts on springs.flick. Double-click a band or press its label and it widens to fill the frame as the seams sweep outward on glide, nearest first, and again sweeps them back to the shares they had. Seams are separators: Tab moves between them, arrows move them (Shift for larger steps), Home and End go to their limits, number keys widen a band and Escape shares it back.

KQ-1611 · BAND/COMPARE

Fernworks grade · harbour, frame 0412

Four passes of one frame

Drag a seam, or Tab to it and use the arrow keys; Shift moves further. Double-click a band, press its label or a number key to widen it to the frame; Escape shares it back.

Raw 25% · Graded 25% · Mono 25% · Dusk 25%

Install

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

$ pnpm dlx shadcn@latest add @kinetiq/band-compare

Props

items
BandCompareItem[]
default defaultBandCompareItems
The versions: { label, src?, alt?, filter?, art? }; the first `bands` are shown.
src
string
default —
The picture every version shares unless it brings its own; defaults to a drawn harbour.
alt
string
default "A harbour at evening with boats and a lighthouse"
Describes the shared picture.
bands
number
default 4
How many versions share the frame, 2 to 6.
seamStyle
"line" | "handle" | "gap" | "fold"
default "handle"
How the seams are drawn: a hairline, a hairline with a grip, a gutter between tiles, or folded strips.
labels
"chip" | "rule" | "none"
default "chip"
How the bands are labelled; "none" keeps the labels for keyboard focus only.
value / defaultValue
number[]
default equal shares
The seam positions, left to right, as fractions of the frame; controlled or initial.
onValueChange
(seams: number[]) => void
default —
Fires from the drag or key that moved a seam, with every seam.
expanded / defaultExpanded
number | null
default null
The band widened to fill the frame, or null; controlled or initial.
onExpandedChange
(index: number | null) => void
default —
Fires from the double-click, label or key that widened a band or shared it back.
minBand
number
default 28
The narrowest a band can be pushed, px.
step
number
default 0.02
How far an arrow key moves a seam, as a fraction of the frame; Shift moves five times as far.
label
string
default "Versions"
The frame's accessible name.
disabled
boolean
default false
No drags, keys or widening; the frame dims.
className
string
default "h-56 w-full"
Sizes the frame.