Skip to content

Scrub Number Field

A compact field you scrub: press its handle and move sideways, or type, or use the arrow keys.

import { ScrubNumberField } from '@youj/react'

Installation & usage

npm i @youj/react

For an app already set up with npx @youj/cli init, which installs the peers (@youj/core, @youj/motion, motion and Base UI) and wires the provider. New app? Start at Installation.

Use a scrub number field where people tune a number by feel and want the exact value too: a position, a blur, a rotation, an opacity. For a quantity entered in a form, with steppers and locale formatting, use a Number Input; for a value on a visible range, a Slider.

import { useState } from 'react'
import { ScrubNumberField } from '@youj/react'

export function Blur() {
  const [blur, setBlur] = useState(24)
  return <ScrubNumberField aria-label="Blur" label="B" unit="px" min={0} max={100} value={blur} onValueChange={setBlur} />
}

The value is a number. Typed text commits on Enter or blur and is clamped but not snapped to the step, so 12.5 stays 12.5; text that isn't a number is put back. Both . and , are read as a decimal separator.

Reference

Propsvalue, defaultValue, onValueChange, min, max, step, label, unit…

Props

ScrubNumberField props
PropType
valuenumber–
defaultValuenumber

default 0

0
onValueChange(value: number) => void–
minnumber–
maxnumber–
stepnumber

Per ArrowUp/Down and per few pixels of drag.

default 1

1
largeStepnumber

Per PageUp/PageDown.

default step * 10

step * 10
labelReactNode

The drag handle: an icon, or a letter. Hidden from assistive tech; name the field with aria-label.

–
unitstring

A plain suffix inside the field: "px", "%", "°".

–
size'sm' | 'default'

sm fits a dense panel.

default 'default'

'default'
localestring

Default: the YoujProvider locale.

–
disabledboolean–
readOnlyboolean–
invalidboolean–
requiredboolean–
namestring–
idstring–
refRef<HTMLInputElement>–
onBlur() => void–
classNamestring–
aria-labelstring

Names the field for assistive tech ("Blur").

–
aria-labelledbystring–

Data attributes

The root carries data-slot="scrub-number-field" and data-size (sm or default), plus data-yj-scrubbing while the handle is being dragged. The handle is scrub-number-field-handle in data-slot.

AccessibilitySpinbutton, keys, value text

Accessibility

  • The field is an input with role="spinbutton" and aria-valuenow, aria-valuemin, aria-valuemax and an aria-valuetext that reads the value with its unit ("24 px"). Name it with aria-label or aria-labelledby; the handle is hidden from assistive technology.
  • ArrowUp and ArrowDown step by step, with Shift ×10 and Alt ×0.1. PageUp and PageDown step by largeStep (default ten steps). Home and End go to min and max.
  • Dragging is an extra for pointer users: everything it does is available from the keyboard.
  • The mouse wheel never changes the value, so a scrolling page doesn't edit a form.
  • Nothing animates, so there is no reduced motion to honor; a drag changes the value directly.