KQ-1148 · STRAIGHTEN/DIAL

Straighten Dial

A photo editor's straighten control: a degree ruler under the picture scrolls 1:1 under the finger and turns the picture about its centre, while a thirds grid fades in for as long as it turns and the crop scales, frame by frame from the same angle, just enough to keep the corners covered. Zero is magnetic: the ruler holds at exactly 0 inside the magnet and catches up at double rate beyond it, the ends rubber-band, and a flick coasts to its projected landing on a critically damped spring while a slow release stays put; rubber-banded releases and keys move on the glide spring. Arrows turn a degree (Shift a tenth), PageUp and PageDown five, Home and End to the ends, with the same ticks and the same snap at zero.

KQ-1148 · STRAIGHTEN/DIAL
Straighten

+2.0° · 1.8° off level

Install

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

$ pnpm dlx shadcn@latest add @kinetiq/straighten-dial

Props

value / defaultValue
number
default 0
The rotation in degrees, clockwise positive, in tenths. Controlled or uncontrolled; a value the host refuses is turned back to once the finger lets go.
onValueChange
(degrees: number) => void
default —
Fires from the drag, key, throw or reset that turned the picture, with the new rotation.
children
React.ReactNode
default —
The picture to straighten. It fills the frame and turns inside it.
aspect
number
default 2
The frame's width over its height. The crop scale is worked out from it.
label
string
default "Straighten"
The ruler's accessible name, shown left of the reading.
range
15 | 45 | "15" | "45"
default "45"
How far it turns either way. The 15° ruler is also the finer one: 12 px a degree against 6, labelled every 5° rather than every 15°.
grid
boolean
default true
Fade a thirds grid over the picture while it turns, and away again once it stops.
magnet
number
default 1.5
How wide the sticky zone around zero is, 0 to 3 degrees, drawn on the ruler. Inside it the ruler holds at exactly 0; 0 makes zero an ordinary degree.
crop
boolean
default true
Scale the picture by the least amount that keeps the frame covered as it turns. Off, it turns at its own size and the empty corners show a checkerboard.
sound
boolean
default false
A fine tick as each degree passes the needle, pitched up the further it is from level, and a snap as zero does. Nothing plays, and no audio context exists, unless this is on.
disabled
boolean
default false
Dims the control, takes the ruler out of the tab order and ignores drags, keys and the reset.
className
string
default —
Merged onto the root's classes.