Components Forms
NumberInput
StableNumeric entry with stepper buttons and full spinbutton keyboard support.
Use NumberInput for quantities with a meaningful range and step: licence seats, reminder intervals, prices. Values are clamped to min and max and rounded to the step precision when the field loses focus. For values picked from a visual range, consider Slider.
Overview
Between 1 and 500.
import { FormField, NumberInput } from '@bindshq/stance-react';
export function Basic() {
return (
<div style={{ width: '100%', maxWidth: 240 }}>
<FormField label="Licence seats" description="Between 1 and 500.">
<NumberInput defaultValue={25} min={1} max={500} />
</FormField>
</div>
);
}Light, dark and high contrast
Every Stance component is designed and tested in all three appearance modes.
Between 1 and 500.
Between 1 and 500.
Between 1 and 500.
Import
import { NumberInput, FormField } from '@bindshq/stance-react';Examples
import { FormField, NumberInput } from '@bindshq/stance-react';
export function Decimal() {
const gbp = new Intl.NumberFormat('en-GB', { style: 'currency', currency: 'GBP' });
return (
<div style={{ width: '100%', maxWidth: 240 }}>
<FormField label="Price per seat">
<NumberInput defaultValue={4.5} min={0} step={0.5} format={(v) => gbp.format(v)} />
</FormField>
</div>
);
}days
import { FormField, NumberInput } from '@bindshq/stance-react';
export function WithAffixes() {
return (
<div style={{ width: '100%', maxWidth: 240 }}>
<FormField label="Send reminders every">
<NumberInput defaultValue={3} min={1} max={30} suffix="days" />
</FormField>
</div>
);
}£
import { FormField, NumberInput } from '@bindshq/stance-react';
export function NoStepper() {
return (
<div style={{ width: '100%', maxWidth: 240 }}>
<FormField label="Contract value">
<NumberInput hideStepper prefix="£" defaultValue={12000} step={100} />
</FormField>
</div>
);
}API reference
| Prop | Type | Default | Description |
|---|---|---|---|
value | number | null | None | Controlled value; null when empty. |
defaultValue | number | null | null | Initial value. |
onValueChange | (value: number | null) => void | None | Called with the committed number. |
min | number | None | Minimum value. |
max | number | None | Maximum value. |
step | number | 1 | Increment for arrows and steppers. |
largeStep | number | 10 | Multiplier for PageUp/PageDown. |
precision | number | None | Decimal places; inferred from step. |
format | (value: number) => string | None | Display formatter; also used for aria-valuetext. |
size | 'sm' | 'md' | 'lg' | 'md' | Control height. |
hideStepper | boolean | false | Hide the increment/decrement buttons. |
prefix / suffix | ReactNode | None | Content inside the field box. |
incrementLabel / decrementLabel | string | 'Increase' / 'Decrease' | Stepper button labels (localise these). |
Accessibility
- Implements the WAI-ARIA spinbutton pattern: role="spinbutton" with aria-valuenow, aria-valuemin, aria-valuemax and aria-valuetext when formatted.
- Uses a text input with inputMode so mobile shows a numeric keypad without the native number input’s scroll-wheel and locale problems.
- Stepper buttons are mouse and touch affordances and are removed from the tab order; the keyboard uses arrow keys instead.
Keyboard
| Keys | Action |
|---|---|
| ArrowUp ArrowDown | Increase or decrease by one step. |
| PageUp PageDown | Increase or decrease by a large step. |
| Home End | Jump to the minimum or maximum (when set). |
| Enter | Commit the typed value. |