Components / Inputs
ScrubInput
A Figma-style number field: drag the label to scrub, or type values, units, and arithmetic.
Install
npx shadcn@latest add https://irisui.dev/r/scrub-input.jsonimport { ScrubInput } from "@/components/iris/scrub-input/scrub-input";Preview
ScrubInput
A compact number field for inspectors: drag the label to scrub, or type values with units and arithmetic.
When to use
- Inspector and properties panels: sizes, positions, rotation, opacity.
- Numeric parameters people tune by feel (storage, spacing) where dragging beats typing.
- Not for picking from a range with a visible handle; use
Slider. - Not for money amounts; use
MoneyInput.
Usage
import { ScrubInput } from "@/components/iris/scrub-input/scrub-input";
const [width, setWidth] = useState(240);
h(ScrubInput, { label: "W", value: width, onValueChange: setWidth, min: 0, units: ["px", "%"], resetValue: 240 });
h(ScrubInput, {
label: "R",
min: 0,
max: 360,
wrap: true,
unit: "°",
units: ["°"],
fineStep: 0.1,
onValueCommit: setRotation,
});
Props
| Prop | Type | Default | Description |
|---|---|---|---|
label |
ReactNode |
required | Text or a 16px icon; dragging it scrubs. Icon labels need aria-label. |
value / defaultValue |
number |
– / 0 |
Controlled or initial value. |
onValueChange |
(value, { source, unit }) => void |
– | Every change, including each scrub step. |
onValueCommit |
(value, details) => void |
– | Once a change settles: scrub end, Enter/blur, or a key step. |
min / max |
number |
-Infinity / Infinity |
Limits. |
step / fineStep / coarseStep |
number |
1 / step/10 (Alt) / step*10 (Shift) |
Step sizes. |
precision |
number |
from fineStep |
Decimal places kept. |
pixelsPerStep |
number |
2 |
Pointer travel per scrub step. |
wrap |
boolean |
false |
Wrap from max to min (needs both limits). |
unit / defaultUnit / units / onUnitChange |
string / string[] |
– | Unit after the number; several units make it a cycling button. |
resetValue |
number |
– | Double-click the label to return here. |
track |
boolean |
on when min and max are set | Quiet fill showing position within the range. |
size |
"sm" | "md" |
"md" |
Field height. |
pointerLock |
boolean |
true |
Lock the pointer while scrubbing where allowed. |
className |
string |
– | Root class; set --scrub-input-width there to size the field (it fills its column by default). |
...input props |
InputHTMLAttributes |
– | Forwarded to the input (disabled, name, ref). |
Notes
- Keyboard: ArrowUp/Down step (Shift coarse, Alt fine); Enter commits typed text including arithmetic; Escape restores while typing or returns to the start while scrubbing.
- The input is a spinbutton with current, min and max values; percent and degree values are spelled out. Invalid text sets
aria-invalidbriefly and keeps the previous value. - Reduced motion removes the edge strain, shake and glide; unit changes fade.
- Reads
hoverfor the resting shell,surfaceandline-strongon focus,redfor an invalid entry, andink-3for the label and unit.