Width and height on one row, with the lock between them: while it is closed, editing one scales the other by the ratio the pair had when the lock closed. Both fields are as wide as the largest number they can hold, so typing never shifts the row.
The import and the props worth knowing about, in one place.
import { InspectorDimensions } from "@/components/beste/component/inspector-dimensions";
<InspectorDimensions label="Size" defaultValue={{ width: 1280, height: 720 }} defaultLocked />
<InspectorDimensions
label="Canvas"
value={size} // { width, height }
onValueChange={setSize} // every accepted edit
onValueCommit={(next) => console.log("settled on", next)} // Enter or blur
locked={locked} // controlled lock; pair it with onLockedChange
onLockedChange={setLocked}
min={16}
max={4096}
step={8} // arrows step by this, Shift by ten of them
precision={0} // decimals kept, which matters because a locked edit divides
suffix="px" // printed once, after the pair
name="canvas" // fields submit as canvas-width and canvas-height
tone="outline" // "muted" (default) | "outline" | "ghost"
size="sm" // "sm" | "default" | "lg"
/>
// A pair whose numbers are genuinely unrelated
<InspectorDimensions label="Grid" lockable={false} defaultValue={{ width: 12, height: 6 }} suffix="" />Every one of these is in the component already. They are listed because a props table cannot mention a gesture, so nothing else on this page can tell you they exist.
| Up / Down | Step the focused number |
|---|---|
| Shift + Up / Down | Step it by ten |
| Enter | Accept what was typed |
| Escape | Throw away what was typed and put the value back |
| Lock | Ties the two together at the ratio they have when it closes |
Read from the component's own type, so this cannot drift from what it accepts.
| Prop | Type | Default | Description |
|---|---|---|---|
label* | string | — | Label rendered on the left, inside the row. |
icon | LucideIcon | — | Optional leading icon shown before the label. |
value | Dimensions | — | Controlled value. Pair it with `onValueChange`. |
defaultValue | Dimensions | — | Initial value in uncontrolled mode. |
onValueChange | (value: Dimensions) => void | — | Fires on every accepted edit. |
onValueCommit | (value: Dimensions) => void | — | Fires once an edit is finished — the field left, or Enter pressed. |
min | number | 0 to 9999, in steps of 1 | Range both numbers answer to. |
max | number | — | |
step | number | — | |
precision | number | 2 | How many decimals a value keeps, which matters here because a locked edit divides. |
suffix | string | "px" | Unit printed after the pair, once, since both numbers are in it. |
locked | boolean | — | Whether the two are tied together. Pair it with `onLockedChange`. While they are, editing one scales the other by the ratio they had when the lock closed. |
defaultLocked | boolean | — | Initial lock state in uncontrolled mode. |
onLockedChange | (locked: boolean) => void | — | |
lockable | boolean | — | Take the lock away, for a pair whose numbers are genuinely unrelated. |
disabled | boolean | — | Block interaction and dim the row. |
tone | "muted" | "outline" | "ghost" | "muted" | Surface treatment: filled (default), hairline outline, or bare until hover. |
size | "sm" | "default" | "lg" | "default" | Row height preset. |
name | string | — | Name of the fields, so the pair can take part in a form. |
className | string | — | |
aria-label | string | — | Accessible name. Falls back to `label`. |