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