Number Field
A number input with plus and minus buttons, keyboard stepping, min/max clamping, Intl formatting and drag-to-scrub labels.
Preview
Usage
import { z } from 'zod'
import { AutoForm } from '@vitnode/core/components/form/auto-form'
import { AutoFormNumber } from '@vitnode/core/components/form/fields/number'const formSchema = z.object({
guests: z.number().int().min(1).max(12).default(2),
})
<AutoForm
formSchema={formSchema}
fields={[
{
id: 'guests',
component: props => (
<AutoFormNumber {...props} label="Guests" max={12} min={1} unitLabel="people" />
),
},
]}
/>The form stores a real number, or null when cleared. Pass min/max to
both: the schema validates, the props clamp.
Need an "unlimited" checkbox? Use Nullable Number.
Min, max and step
min/max disable the button at a limit and clamp typed values on blur.
step is one press, largeStep adds Shift, smallStep adds
Alt. snapOnStep snaps to the nearest multiple.
<NumberField largeStep={50} max={500} min={0} snapOnStep step={5}>
…
</NumberField>Formatting
format takes Intl.NumberFormatOptions.
The value stays a number: 0.15 shows as 15%. Formatting follows the app
locale unless you pass locale.
<NumberField
defaultValue={19.99}
format={{ style: 'currency', currency: 'USD' }}
>
…
</NumberField>Scrub area
Drag the label in the preview sideways. NumberFieldScrubArea
makes a label scrubbable. Pass the field's id as htmlFor so a click still
focuses the input.
const id = React.useId()
<NumberField id={id} max={8} min={0}>
<NumberFieldScrubArea htmlFor={id} label="Coffees per day" />
<NumberFieldGroup>…</NumberFieldGroup>
</NumberField>allowWheelScrub adds mouse-wheel changes while focused.
Sizes
<NumberField size="sm">…</NumberField>Disabled and read-only
readOnly stays focusable, unlike disabled.
Accessibility
- The input is a text field with
inputMode, so$19.99fits and phones show a number pad. - ↑ / ↓ step, Home / End jump to
min/maxwhen set. - The buttons are labelled "Increase" / "Decrease", skip Tab, and grow to a 44px hit area on touch.
- Name the input with a label (
htmlFor+id), a scrub area oraria-label.AutoFormNumberdoes it for you.
Props
Prop
Type
AutoFormNumber takes all of these except value, defaultValue and
onValueChange (the form owns them), plus label, description,
placeholder and unitLabel.