KQ-1133 · RATIO/MORPH

Ratio Morph

An aspect-ratio picker that reframes a picture: choosing a shape glides the frame's width and height to the new ratio on the glide spring, with four corner brackets riding its corners, while the picture is re-laid every frame so its focal point stays as near the centre as its edges allow. Pressing the stage brings the focal reticle to the finger 1:1 (it swells on flick) while a ghost of the whole picture fades in round the frame; past the picture's edge the reticle rubber-bands, and on release the throw is projected and the picture glides to re-centre on the new point. The chips are a radiogroup whose arrows choose and whose Home and End jump; the stage takes arrow keys (Shift for bigger steps) to move the focal point with the same glide and sounds.

KQ-1133 · RATIO/MORPH

Harbour at dusk with a lighthouse on the headland. Drag or tap to place the focal point, or use the arrow keys; Shift moves further.

4:5 portrait · focus 25% across, 54% down

Install

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

$ pnpm dlx shadcn@latest add @kinetiq/ratio-morph

Props

ratios
"social" | "photo" | "screen" | string[]
default "social"
The shapes offered, in chip order: social is 1:1, 4:5, 16:9 and 9:16; photo is 3:2, 4:3, 1:1 and 2:3; screen is 16:9, 16:10, 21:9 and 4:3. Or your own list of "w:h" strings. RATIO_MORPH_SETS exports the named sets.
value / defaultValue
string
default the first of ratios
The chosen ratio, as "w:h". A value that is not in the list shows the first ratio.
onValueChange
(ratio: string) => void
default —
Fires from the press or key that chose a new ratio. In controlled mode the frame morphs once the host passes the new value back.
focalPoint / defaultFocalPoint
{ x: number; y: number }
default { x: 0.5, y: 0.5 }
The point the frame keeps in view as it changes shape, as fractions of the picture's width and height.
onFocalPointChange
(point: { x: number; y: number }) => void
default —
Fires once per drag release, tap or arrow key, with the new point rounded to three places.
brackets
number
default 16
The corner brackets' arm length in px, 6 to 40: short ticks to nearly closed corners.
focal
boolean
default true
Marks the focal point with a reticle on the picture.
grid
boolean
default false
Rule-of-thirds lines inside the frame that ride the morph; faint at rest, brighter while the picture is held.
picture
ReactNode
default a procedural harbour at dusk
What is framed. It is laid out in a box of pictureRatio and scaled, so pass something that fills its box, such as an img with object-cover.
pictureRatio
number
default 1.5
The picture's own width over its height.
alt
string
default —
What the picture shows, read with the stage's instructions. Defaults to a description of the built-in harbour.
label
string
default "Aspect ratio"
The ratio chips' accessible name.
sound
boolean
default false
A detent when a ratio is chosen and a click on the frame the morph lands, both pitched by the shape; a detent when a drag meets the picture's edge and a click on release. Nothing plays, and no audio context exists, unless this is on.
disabled
boolean
default false
Dims the picker and blocks the chips, drags, taps and keys.
className
string
default —
Merged onto the wrapper that holds the stage and the chips.