Settings row for a ratio: the row prints it and draws it, and opens an editor with the ratios worth a name plus both sides always editable. It is kept as two numbers rather than as their quotient, since 16:9 is what a reader recognises.
Adds the component and everything it depends on to your project.
npx shadcn add https://ui.beste.co/component/r-base/inspector-aspectNew here? Read the installation guide.
The import and the props worth knowing about, in one place.
import { InspectorAspect } from "@/components/beste/component/inspector-aspect";
// Uncontrolled
<InspectorAspect label="Aspect Ratio" defaultValue={{ w: 16, h: 9 }} />
// Controlled, with a separate commit for expensive work
<InspectorAspect
label="Aspect Ratio"
value={ratio}
onValueChange={setRatio}
onValueCommit={(value) => save(value)}
/>
<InspectorAspect
label="Thumbnail"
icon={RatioIcon} // optional leading icon
tone="outline" // "muted" (default) | "outline" | "ghost"
size="sm" // "sm" | "default" | "lg"
maxSide={64} // largest either side may be
presets={[ // shortcuts, not the set of allowed answers
{ w: 1, h: 1, label: "Square" },
{ w: 4, h: 5, label: "Feed" },
]}
value={ratio}
onValueChange={setRatio}
/>
// What the value turns into
<div style={{ aspectRatio: `${ratio.w} / ${ratio.h}` }} />
// Sides are reduced by their common factor for display, so a value of 1920 by 1080
// still reads as 16:9. A ratio nobody named is still a ratio, so the menu
// simply sits on "Custom".Turn the props on the right; the snippet under them is what you would write to get what you see.
import { InspectorAspect } from "@/components/beste/component/inspector-aspect";
<InspectorAspect
label="Aspect Ratio"
className="w-72"
defaultValue={{"w":16,"h":9}}
/>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 | AspectValue | — | Controlled value. Pair it with `onValueChange`. |
defaultValue | AspectValue | — | Initial value in uncontrolled mode. |
onValueChange | (value: AspectValue) => void | — | Fires on every adjustment. |
onValueCommit | (value: AspectValue) => void | — | Fires once an adjustment is finished — a preset chosen, a side committed. Use it for work too expensive to run per keystroke. |
onOpenChange | (open: boolean) => void | — | Fires when the editor opens or closes. |
presets | AspectPreset[] | the six ratios anyone can name | Which ratios to offer by name. The two sides stay editable regardless, so this is a set of shortcuts rather than a set of allowed answers. |
maxSide | number | 100 | Largest either side may be. |
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. |
className | string | — | |
aria-label | string | — | Accessible name. Falls back to `label`. |
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.
Settings row whose choices sit side by side on the right, with a marker that slides between them: the readable alternative to a switch when the two states deserve names, and the compact one to a select at three or four options.
Settings row for a border: the row draws one exactly as described beside a summary of it, and opens an editor with the sides as icon toggles and the width, style and colour under them, each one a row of the family.
Settings row for a span rather than a value: two thumbs on the row itself, the band between them filling it, and both ends of the pair read out on the right. Ticks, tones and thumb states follow inspector-slider exactly, appearing on hover.