build69
build69  /  Components  /  Text Inputs  /  NumberInput

NumberInput

v1.0.5Updated 28 Sept 2026

Numeric spinbutton field with min/max clamping, step increments (keyboard + hold-to-repeat stepper buttons) and Intl.NumberFormat display when blurred — decimal, currency (default THB) or percent. Shows the raw editable

Preview

Live · 13 stories
DefaultOpen ↗
▸Why this is recommendednumberspinbuttonsteppercurrency+5

The default, out-of-the-box NumberInput.

Recommended for+14
  • ✓Invoice quantities and unit prices (THB)
  • ✓VAT / discount percentage fields
  • ✓Stock reorder levels
  • ✓Any bounded numeric entry
Tags+6
numberspinbuttonsteppercurrencypercentthbquantitymoneydefault
Features+4
  • Controlled (value/onValueChange) and uncontrolled (defaultValue) modes, null = empty
  • min / max clamping on blur and on every step
  • step increments with hold-to-repeat stepper buttons
  • Keyboard: ArrowUp/Down = step, PageUp/Down = 10x step, Home/End = min/max
  • precision rounding without floating-point residue
  • Intl formats: 'decimal' | 'currency' (currency prop, default THB) | 'percent' (value 7 renders 7%)
  • Locale prop (default th-TH)
  • prefix / suffix adornments
  • role=spinbutton with aria-valuenow / valuemin / valuemax / valuetext
  • disabled / readOnly / error states, sizes sm / default / lg
  • Hidden input carries the raw number for form submission when name is set
  • i18n: labels prop overrides the stepper aria-labels
Not recommended for−2
  • ✕Free-form text (use Input)
  • ✕Continuous ranges with visual feedback (use Slider)
  • ✕Phone numbers or IDs (use InputMask)

Install

Ask your agent, or call the MCP tool directly. The resolved bundle is written into your project.

get_registry_item({ name: "NumberInput" })

Usage

import { NumberInput } from '@/components/inputs/number-input';

<NumberInput label="Unit price" format="currency" currency="THB" precision={2} min={0} step={10} defaultValue={1290} />

Tick variants in the left menu — each adds a tab with that variant’s real story source, the same code the preview above renders.

Props

PropTypeRequired
value

Controlled value; null = empty

number | null—
defaultValue

Uncontrolled initial value

number | null—
onValueChange

Fires with the parsed number

(value: number | null) => void—
min

Lower clamp bound

number—
max

Upper clamp bound

number—
step

Increment for arrows/steppers (default 1)

number—
precision

Decimal places rounded to on commit

number—
format

Blurred display format

'decimal' | 'currency' | 'percent'—
currency

ISO 4217 code for currency format (default THB)

string—
locale

BCP 47 locale (default th-TH)

string—
prefix

Leading in-field adornment

ReactNode—
suffix

Trailing in-field adornment

ReactNode—
showSteppers

Show up/down buttons (default true)

boolean—
size

Field size

'sm' | 'default' | 'lg'—
label

Field label

string—
hint

Helper text below the field

string—
error

Error message; flips invalid styling

string—
labels

Override built-in UI strings (i18n)

Partial<NumberInputLabels>—
aria-invalid

Mark the field invalid from outside; the box paints the same destructive state as its own validation, with the alert in its own trailing slot (FormField clones this in from its error prop)

boolean—
aria-describedby

Id(s) of outside hint or error text, kept alongside the messages the field owns (FormField clones this in)

string—
aria-required

Mark the input required for assistive tech (FormField clones this in from its required prop)

boolean—
aria-label

Accessible name where the layout has no room for a visible `label` — a filter row, a subscribe box beside its button. Prefer `label`: a visible one names the field for everybody. These components destructure a fixed prop set and used to DROP an aria-label a caller wrote, so such a field announced as nothing but its role.

string—

Related