Inspector Unit

About this component

Inspector Unit

A number and the unit that gives it meaning, in one row: px, rem, a percentage, or a keyword like auto that is the whole value on its own. Each unit may bring its own range, so a percentage stops at 100 while pixels do not.

Usage

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

import { InspectorUnit } from "@/components/beste/component/inspector-unit";

// Uncontrolled
<InspectorUnit label="Width" defaultValue={{ value: 100, unit: "%" }} />

// Controlled, with a separate commit for expensive work
<InspectorUnit
  label="Max width"
  value={width}
  onValueChange={setWidth}
  onValueCommit={(value) => save(value)}
/>

// A unit that is the whole value: the number field steps aside rather than sitting
// there holding a figure that means nothing
<InspectorUnit
  label="Height"
  units={["px", "%", "vh", { value: "auto", valueless: true }]}
  value={height}
  onValueChange={setHeight}
/>

// A range per unit, since 0 to 100 reads as a percentage and 0 to 9999 does not
<InspectorUnit
  label="Offset"
  units={[
    { value: "px", min: -400, max: 400 },
    { value: "%", min: -100, max: 100 },
    { value: "rem", min: -24, max: 24, step: 0.25 },
  ]}
  value={offset}
  onValueChange={setOffset}
/>

<InspectorUnit
  label="Letter spacing"
  icon={TypeIcon}     // optional leading icon
  tone="outline"      // "muted" (default) | "outline" | "ghost"
  size="sm"           // "sm" | "default" | "lg"
  units={["em", "px"]}
  step={0.01}
  precision={3}       // decimals kept on commit
  name="tracking"     // submits as tracking and tracking-unit
  value={tracking}
  onValueChange={setTracking}
/>

// What the value turns into
const css = value.unit === "auto" ? "auto" : `${value.value}${value.unit}`;

// The arrows work the field the way they work a stepper, and Shift moves ten steps.

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.

Arrow Up / DownOne step on the number, the way a stepper moves: a length is a number first and a string second.
Shift + ArrowTen steps.
EnterAccept what was typed.
EscapeThrow the draft away and put the committed value back.

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.
valueUnitValue—Controlled value. Pair it with `onValueChange`.
defaultValueUnitValue—Initial value in uncontrolled mode.
onValueChange(value: UnitValue) => void—Fires on every accepted edit and on every unit change.
onValueCommit(value: UnitValue) => void—Fires once an edit is finished — the field left or Enter pressed, a unit chosen. Use it for work too expensive to run per keystroke.
units(string | InspectorUnitOption)[]["px", "%", "rem"]The units on offer. Plain strings are enough when the unit is its own label.
minnumber0 to 9999, in steps of 1Range the number answers to, for units that do not name their own.
maxnumber—
stepnumber—
precisionnumber2How many decimals a value keeps. Anything typed past this is rounded on commit, so what the field shows is what the caller was handed.
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 number field, so the row can take part in a form.
idstring—Id of the number field, for an external `<label htmlFor>`.
classNamestring—
aria-labelstring—Accessible name. Falls back to `label`.

More Inspector components

View all Inspector
Contrast5.30:1
Applies to every breakpoint.