Components / Inputs

NumberField

Enter a bounded number with clear increment controls.

Install

npx shadcn@latest add https://irisui.dev/r/number-field.json
import { NumberField } from "@/components/iris/number-field/number-field";
Registry item number-fieldBrings in foundationRegistry JSON

Preview

NumberField

A bounded number stepper with odometer digits, prefix and suffix text, hold-to-repeat buttons and an optional scrubbable label.

When to use

  • Counts and amounts with clear limits: seats, rent, price per m², publish attempts.
  • When units matter; suffix can pluralise (n => n === 1 ? " seat" : " seats").
  • For picking from a continuous range by feel use Slider or ElasticSlider; for free text use Input.

Usage

import { NumberField } from "@/components/iris/number-field/number-field";
function Seats() {
  const [seats, setSeats] = React.useState(3);
  return h(NumberField, {
    label: "Seats",
    value: seats,
    onValueChange: setSeats,
    min: 1,
    max: 10,
    suffix: (n) => (n === 1 ? " seat" : " seats"),
    scrub: true,
  });
}

Props

Prop Type Default Description
label string required Visible label; also names the stepper buttons.
value / defaultValue number – / 0 Controlled or initial value.
onValueChange (value: number) => void – Called on every committed step, scrub or valid typed draft.
min / max number 0 / Number.MAX_SAFE_INTEGER Bounds.
step number 1 Increment; its precision sets default fraction digits.
largeStep number step × 10 PageUp/PageDown and Shift+arrow distance.
prefix / suffix string | ((value: number) => string) – Text before or after the number, such as "€" or " seats".
scrub boolean false Drag the label sideways to change the value.
size "sm" | "md" | "lg" "md" Height, type size and default width (164, 196 or 228px).
limitHint boolean | ((edge, limit) => string) true Short note beside the label when a press meets a limit; false hides it.
locale / formatOptions string / { minimumFractionDigits, maximumFractionDigits, useGrouping } "en-US" / – Number formatting.
description / disabled / id string / boolean / string – Helper copy, disabled state, input id.

Notes

  • The input has role="spinbutton"; arrows step, PageUp/PageDown and Shift+arrow take largeStep, Home/End jump to the limits. The buttons are labelled "Increase …" / "Decrease …".
  • Presses past a limit strain toward it and spring back; held buttons repeat with gentle acceleration. Reduced motion removes the digit roll and strain.
  • The width comes from --number-field-width (or the size default); the label row matches it so the limit note sits above the stepper.
  • Theme: surface, line / line-strong (border), ink (focus border), orange (limit note and out-of-range tint), rounded-control (shell), rounded-button (steppers), control heights.