StackForm
Components

NumberField

Numeric input field with optional min, max, step, and increment/decrement stepper buttons

NumberField renders a labeled, accessible <input type="number"> connected to the active form adapter via context. It supports optional stepper buttons, min/max bounds, and custom step values. Error and hint states surface automatically — no prop wiring needed.

Props

PropTypeRequiredDefaultDescription
namestringyesField name. Used as the form state key and to derive element IDs.
labelstringLabel text rendered above the input.
hintstringHelper text shown below the input when no error is present.
placeholderstringPlaceholder text for the input.
minnumberMinimum allowed value. Clamps stepper decrement.
maxnumberMaximum allowed value. Clamps stepper increment.
stepnumber1Increment/decrement step size. Also applied to native stepper arrows.
showStepperbooleanfalseShows increment/decrement buttons.
disabledbooleanfalseDisables the input. Inherits from StackFormProvider if not set.
loadingbooleanfalseReplaces the input with a skeleton shimmer.
requiredbooleanfalseMarks the field as required. Appends * to the label.
formatIntl.NumberFormatOptionsNumber formatting options. Reserved — not applied to the native input in the current release.
classNamesNumberFieldClassNamesTailwind class overrides per slot. Stacks with provider and core classes.
slotsNumberFieldSlotsComponent overrides per slot. First non-null wins: field → provider → default.
slotProps{ wrapper?, label?, input?, error?, hint? }Extra props passed to each slot. Field-level replaces provider-level per key.
onValueChange(value: number) => voidCalled after onChange with the new value.
validate(value: number) => string | undefined | Promise<string | undefined>Field-level validator. Runs on blur.

Slots

SlotProp interfaceDescription
WrapperWrapperSlotPropsOuter container element
LabelLabelSlotPropsLabel element
InputNumberInputSlotPropsThe <input type="number"> element
ErrorErrorSlotPropsError message
HintHintSlotPropsHint/helper text
StepperIncrementStepperButtonSlotPropsIncrement button
StepperDecrementStepperButtonSlotPropsDecrement button

classNames

KeyApplied to
wrapperOuter container
labelLabel element
inputInput element
errorError message
hintHint text
stepperIncrementIncrement button
stepperDecrementDecrement button

Examples

With error

Errors surface automatically from the form adapter. Trigger one manually to test:

form.setError('price', { message: 'Price must be a valid number' })

<NumberField name="price" label="Price" />

With hint

<NumberField
  name="age"
  label="Age"
  hint="Enter your age in years."
  min={0}
  max={150}
/>

With min, max, and stepper

<NumberField
  name="quantity"
  label="Quantity"
  placeholder="1"
  min={1}
  max={100}
  step={1}
  showStepper
/>

With step and hint

<NumberField
  name="price"
  label="Price (USD)"
  placeholder="0.00"
  step={0.01}
  min={0}
  hint="Enter price in dollars and cents."
/>

With slot override

Replace the default increment/decrement buttons with custom components. Slot components receive only display-level props.

import type { StepperButtonSlotProps } from '@stackform/ui'

function StepButton({ direction, onClick, disabled, className }: StepperButtonSlotProps) {
  return (
    <button
      type="button"
      onClick={onClick}
      disabled={disabled}
      aria-label={direction === 'increment' ? 'Increase value' : 'Decrease value'}
      className={className}
    >
      <span aria-hidden="true">{direction === 'increment' ? '+' : '−'}</span>
    </button>
  )
}

<NumberField
  name="quantity"
  label="Quantity"
  min={0}
  showStepper
  slots={{ StepperIncrement: StepButton, StepperDecrement: StepButton }}
/>