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.
The import and the props worth knowing about, in one place.
import { InspectorRange } from "@/components/beste/component/inspector-range";
// Uncontrolled
<InspectorRange label="Price" min={0} max={300} step={5} defaultValue={[40, 220]} unit="$" />
// Controlled, with a separate commit for expensive work
<InspectorRange
label="Duration"
value={window}
onValueChange={setWindow} // every thumb move
onValueCommit={(value) => console.log("fetch", value)} // on release
min={0}
max={60}
step={1}
unit="s"
/>
<InspectorRange
label="Opacity"
icon={Contrast} // optional leading icon
min={0}
max={1}
step={0.05}
separator="to" // "–" by default
formatValue={(value) => `${Math.round(value * 100)}%`}
minStepsBetweenThumbs={2} // keeps the thumbs apart
ticks={false} // true by default: they show on hover
value={opacity}
onValueChange={setOpacity}
tone="outline" // "muted" (default) | "outline" | "ghost"
size="sm" // "sm" | "default" | "lg"
/>Turn the props on the right; the snippet under them is what you would write to get what you see.
import { InspectorRange } from "@/components/beste/component/inspector-range";
<InspectorRange
label="Price"
className="w-72"
max={300}
step={5}
defaultValue={[40,220]}
unit="$"
/>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.
| Tab | Move between the two thumbs. |
|---|---|
| Arrow keys | One step on the focused thumb. |
| Home / End | Send the focused thumb to its end of the range. |
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 | [number, number] | — | Controlled pair, low then high. Pair it with `onValueChange`. |
defaultValue | [number, number] | — | Initial pair in uncontrolled mode. Falls back to the whole range. |
onValueChange | (value: [number, number]) => void | — | Fires on every thumb move. |
onValueCommit | (value: [number, number]) => void | — | Fires when a thumb is released. Use it for work too expensive per frame. |
min | number | 0 | Minimum value. |
max | number | 100 | Maximum value. |
step | number | 1 | Smallest increment. Also drives how many decimals the readout shows. |
formatValue | (value: number) => string | — | Format each end of the readout. Defaults to the number plus `unit`. |
unit | string | — | Suffix on the default readout, e.g. "px", "%". |
separator | string | — | Text between the two numbers. |
ticks | boolean | number | number[] | true | Tick marks inside the row: `true` for automatic (one per step up to 12, otherwise deciles), a count, an explicit list of values, or `false`. They appear on hover, as they do on the single slider. |
minStepsBetweenThumbs | number | 1 | Steps to keep between the thumbs, so they cannot cross or stack. |
disabled | boolean | — | Block interaction and dim the row. |
tone | "muted" | "outline" | "ghost" | "muted" | Surface treatment: filled (default), hairline outline, or bare. |
size | "sm" | "default" | "lg" | "default" | Row height preset. |
name | string | — | Name of the underlying inputs, so the row can take part in a form. |
className | string | — | |
aria-label | string | — | Accessible name. Falls back to `label`. |
Compact settings row where the label and the live value sit inside the track: magnetic tick snapping, a rubber band when you overdrag, Shift for precision, Alt-click to reset, wheel and typed input, an option to keep the handle on show while idle, on a native range input for full accessibility.
Settings row for a point on a surface: the row names the nine spots CSS names and shows the rest as two percentages, and opens a square pad the point is dragged around, with the thirds drawn on it and a pull towards them.
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 for a direction: a dial you drag round, reading in degrees the way CSS does (zero up, growing clockwise), with a range input underneath carrying the keyboard and the form.
The strip that splits a settings panel into two or three questions instead of one long scroll. It is the strip and nothing else: what the tabs switch between stays in the panel's own markup, beside the state that decides it. The pill slides between equal columns, arrow keys both move and select, and a tab can carry a count of what has changed under it.