Number Input
A numeric input with increment / decrement steppers on Ark UI's NumberInput machine — clamping, locale-aware formatting, mouse-wheel, and the full keyboard model on the shared input shell.
NumberInput is a numeric <input> with spin buttons, built on Ark UI's NumberInput machine and the same shell as Input. It clamps to a range, formats with Intl.NumberFormat, supports the mouse wheel, and ships the full keyboard model (↑ / ↓ step, PageUp / PageDown jump, Home / End to min / max).
import { NumberInput } from '@42/ui-react/number-input';
<NumberInput defaultValue={3} min={0} max={10} />The value is a real number (or null for empty) — the machine speaks strings internally, but value / defaultValue take a number | null and onChange hands one back, null whenever the field has no valid number. Like the rest of the family it carries its own label, description, error, and required — no external wrapper needed — and passing error flips it to the invalid (red) state. Omit them and it still composes cleanly inside a Field.
Playground
Component
Dir
Presets
Props
Code
<Component label="Slots" size="md" step={1}/>Min, max & step
min / max clamp the range; step sets the spin amount. With allowMouseWheel, scrolling over a focused input nudges the value too.
Formatting
formatOptions is forwarded straight to Intl.NumberFormat, so currency, percent, and unit display come for free — the parsed value stays a plain number.
Sizes
Five heights — xs through xl — matching the rest of the family. The control font, padding, and the steppers scale to match.
Code
<NumberInput size="xs" defaultValue={1} /><NumberInput size="sm" defaultValue={1} /><NumberInput size="md" defaultValue={1} /><NumberInput size="lg" defaultValue={1} /><NumberInput size="xl" defaultValue={1} />No controls
hideControls drops the steppers for a plain numeric field — useful inside dense forms where the spin buttons would crowd the layout.
Clearable
clearable adds a clear (×) button once there's a value — the numeric analogue of Select's clearable. Clicking it resets the field to null. placeholder shows while the field is empty.
Colors
Like the rest of the form family, the resting input is palette-independent — only the focus ring references --c-solid, so each palette tints the focus state for free. See Colors.
Code
<NumberInput color="brand" defaultValue={1} /><NumberInput color="green" defaultValue={1} /><NumberInput color="purple" defaultValue={1} />Invalid & disabled
invalid swaps the border and ring to red regardless of color (and sets aria-invalid). disabled dims the shell and blocks input; readOnly keeps full contrast but rejects edits.
Code
<NumberInput invalid defaultValue={5} /><NumberInput disabled defaultValue={5} /><NumberInput readOnly defaultValue={5} />With label, description & error
label, description (helper text), and error are built in via Field — no external wrapper needed. Passing error flips the shell to the invalid (red) state; required adds the semantic flag and a red asterisk on the label.
Code
<NumberInput label="Slots" description="How many evaluation slots to book." defaultValue={1} min={1} /><NumberInput label="Slots" required defaultValue={1} min={1} /><NumberInput label="Slots" error="Pick at least one" defaultValue={0} min={1} />If you omit these props, the control still composes inside an outer Field, inheriting the field's invalid, disabled, and readOnly from context — so an error on the field flips the input red automatically.
Controlled
Drive the value from state. onChange hands you a number, or null while the field is empty or mid-edit.
'use client';
import { useState } from 'react';
import { NumberInput } from '@42/ui-react/number-input';
export function Slots() {
const [value, setValue] = useState<number | null>(1);
return <NumberInput value={value} onChange={setValue} clearable min={1} max={99} />;
}Forms
A name wires the underlying input into native <form> submission and FormData — no controlled state required.
<form action={save}>
<NumberInput name="slots" defaultValue={1} min={1} />
</form>API
Prop
Type
Accessibility
- Full NumberInput keyboard model from Ark:
↑/↓step,PageUp/PageDownjump by a larger step,Home/Endsnap to min / max. - The input is
role="spinbutton"witharia-valuemin/aria-valuemax/aria-valuenow/aria-valuetextwired from the machine. invalidsetsaria-invalid. Passlabel/description/errorfor an accessible name and error text via the built-inField, or compose inside an outerFieldinstead.- The steppers are real
<button>s withIncrement/Decrementlabels; the wheel and scrub gestures are progressive enhancements over keyboard / typing. suffixis decorative only —aria-hiddenand non-selectable, never part of the editable value or the accessible name. To show a compact unit hint without a visible label, keep passinglabel(it stays the accessible name) and visually hide it withclassNames={{ label: "sr-only" }}.
Password Input
A native password field with a built-in show / hide toggle, in the shared input shell — bordered or filled box, focus ring, and invalid / disabled states, plus a built-in label, description, and error.
Pin Input
A row of single-character cells for one-time codes and PINs on Ark UI's PinInput machine — autofocus advance, paste-to-fill, masking, OTP autofill, and native form submission.