Inspector Scrub

em
About this component

Inspector Scrub

A number with no ends, dragged from the row itself: for the values that have no maximum worth naming, like a z-index, an X offset or a letter-spacing. The drag is relative rather than positional, so pressing anywhere is safe, and a soft range gives the bar something to draw against that the value is free to leave. Only the reported number is quantized, so the pointer never fights the grid.

Usage

The import and the props worth knowing about, in one place.

import { InspectorScrub } from "@/components/beste/component/inspector-scrub";

// Both bounds optional, which is the point: neither of these has an honest maximum
<InspectorScrub label="Letter spacing" defaultValue={0} step={0.01} suffix="em" sensitivity={8} />

// The bar, for a number that has no ends. `softMin`/`softMax` are the span worth
// working in, not a limit: the fill shows where the value sits in that span, pins
// once it is past it, and the number carries on. With no span there is no bar,
// since a bar over an unknown range would have to invent one.
<InspectorScrub label="Letter spacing" softMin={-0.1} softMax={0.4} step={0.01} suffix="em" />

<InspectorScrub
  label="X offset"
  value={x}
  onValueChange={setX}                       // every step of the drag
  onValueCommit={(next) => console.log("settled on", next)}  // when the drag ends
  step={1}
  precision={0}
  sensitivity={4}      // pixels of drag per step; lower is faster
  suffix="px"
  name="x-offset"
  tone="outline"       // "muted" (default) | "outline" | "ghost"
  size="sm"            // "sm" | "default" | "lg"
/>

// Bounded on one side only, which no slider can express
<InspectorScrub label="Z index" min={0} step={1} precision={0} />

Keyboard and gestures

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.

Hover the rowLights the whole track and shows the grip
Drag the rowRuns the number with the pointer, from wherever you pressed
Shift + dragTen times the step
Alt + dragA tenth of it
Click the labelPuts the caret in the field to type an exact value
Up / DownStep the value; Shift for ten of them
EscapeThrow away what was typed

Props

Read from the component's own type, so this cannot drift from what it accepts.

PropTypeDefaultDescription
label*string—Label rendered on the left, inside the row.
iconLucideIcon—Optional leading icon shown before the label.
valuenumber—Controlled value. Pair it with `onValueChange`.
defaultValuenumber—Initial value in uncontrolled mode.
onValueChange(value: number) => void—Fires on every change, including each step of a drag.
onValueCommit(value: number) => void—Fires when a drag ends or an edit is committed.
minnumber—Hard bounds, both optional, which is the point of this row. A z-index, an X offset or a letter-spacing has no honest maximum, and a slider that invents one is a slider whose whole range is a lie. What is given here the value is held to.
maxnumber—
softMinnumber—The range the **bar** is drawn against, which the value is free to leave. It is how an endless number gets a picture: the fill shows where the value sits in the span you would usually be working in, pins at the end once it is past that, and the number keeps going. Give both or neither. Falls back to `min` and `max`, so a row with hard bounds already looks like a slider, and a row with none has no bar at all rather than a made-up one.
softMaxnumber—
stepnumber1What one step of the drag is worth, and what the arrows move by.
precisionnumber2How many decimals the reported value keeps.
sensitivitynumber4Pixels of drag per step. Lower is faster; the default asks for four pixels a step, which is quick enough to cross a range and slow enough to land on a number.
suffixstring—Printed after the number, e.g. `px`, `%`, `em`.
disabledboolean—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.
namestring—Name of the field, so the row can take part in a form.
idstring—Id of the field, for an external `<label htmlFor>`.
classNamestring—
aria-labelstring—Accessible name. Falls back to `label`.

More Inspector components

View all Inspector