NumberInput

Numeric input with stepper buttons, clamping, precision, and locale formatting

Category: inputs · WCAG 2.2-AA · form, number, input, spinbutton, stepper

Sizes

States

Props

PropTypeDefaultDescription
valuenumber | null—The controlled value.
defaultValuenumber—The initial value when uncontrolled.
onValueChange(value: number | null) => void—Fired on commit (blur, Enter, stepping); null when empty or unparseable
minnumber—Minimum allowed value.
maxnumber—Maximum allowed value.
stepnumber1Increment between allowed values.
precisionnumber—Decimal places applied on commit
formatOptionsIntl.NumberFormatOptions—Display formatting applied on blur; raw editable string while focused
labelstring—Text label for the control.
hintstring—Supplementary hint text shown with the control.
errorstring—Error message shown when the value is invalid.
size'sm' | 'md' | 'lg'mdVisual size of the component (e.g. 'sm', 'md', 'lg').
disabledbooleanfalseWhen true, disables the control and removes it from the tab order.
incrementLabelstringIncrementAccessible label for the increment button.
decrementLabelstringDecrementAccessible label for the decrement button.
ariaLabelstring—Invisible accessible name, for when a visible element outside this component already labels it and `label` would render that text a second time. ⚠ `label` on this component is **visible**; `IconButton.label`/`Sparkline.label` are invisible names, which is the prior that costs adopters a duplicated label. The raw DOM `aria-label` still wins over this.

Design tokens

When to use

When not to use

How to build an accessible NumberInput in React →

Examples

Basic

<NumberInput label="Quantity" defaultValue={1} min={0} max={99} />

Currency

<NumberInput label="Price" precision={2} formatOptions={{ style: "currency", currency: "USD" }} />

Stepped

<NumberInput label="Opacity" min={0} max={1} step={0.1} />

Related components

← Back to docs