Components/ScrubField

ScrubField

A compact numeric field whose label is the drag handle.

VerifiedSince 0.3.9

Usage

Basic

An integer, a percentage, and a half step.

Loading demo...

Best Practices

  • Keep labels short (W, H, Radius); the label is the drag handle.
  • Let the host decide active, usually "value differs from the preset", compared against data rather than a constant.
  • Use clampOn="blur" in forms people type into; keep the default 'input' in inspectors with a live preview.
  • Use TxSlider to pick a value by position on a track, and TxNumberInput for a form field with stepper buttons.

API Reference

Props

NameTypeDefaultDescription
modelValuenumber—The current value (controlled).
labelstring—Short label that doubles as the drag handle.
min / maxnumber—Bounds; dragging, arrow keys, and typing all clamp to them.
stepnumber1Step size; a fractional step keeps its decimals.
suffixstring—Unit after the value, such as %.
activebooleanfalseTints the field as changed; the host decides what counts as changed.
disabledbooleanfalseDisables dragging, arrow keys, and typing.
pixelsPerStepnumber2Pointer travel that advances one step.
shiftMultipliernumber10Arrow-key multiplier while Shift is held.
clampOn'input' | 'blur''input'When typed text is clamped: on every keystroke or on blur.
ariaLabelstring—Accessible name for the handle; falls back to label.
valueLabelstring'{label} value'Accessible name for the input.

Events

EventPayloadDescription
update:modelValue(value: number)Fires when the value changes; never repeats an identical value.
change(value: number)Fires together with update:modelValue.
scrubStart / scrubEnd—Start and end of a drag, cancellation included.

Exposed Methods

MethodDescription
focus()Focuses the drag handle.
focusInput()Focuses the number input.

Overview

  • Drag: move sideways on the label; every pixelsPerStep pixels advance one step, measured from the gesture's start, with no track. Escape during a drag restores the starting value.
  • Keyboard: ↑ → increase, ↓ ← decrease, Shift multiplies by shiftMultiplier, and Home / End jump to the bounds.
  • Typing: the value is a native <input>; clampOn="blur" keeps the typed text until blur. Escape reverts the text.
  • The handle is a role="slider" with aria-valuenow / aria-valuemin / aria-valuemax / aria-orientation, plus aria-valuetext when suffix is set; the input is a second control with its own accessible name.
  • The handle sets touch-action: pan-y, leaving vertical gestures to page scroll; pointercancel and lostpointercapture both end a drag.
  • Under reduced motion, the only state transition is switched off.

Technologies

  • Travel is quantised, not the result: round(distance / pixelsPerStep) * step, so fractional steps work and an off-grid starting value is not snapped.
  • Source: packages/tuffex/packages/components/src/scrub-field/.
  • Adapted from Beautiful UI (https://www.beautifului.dev), © 2026 Shane Levine, MIT.
查看源码
packages/tuffex/packages/components/src/scrub-field/index.ts