InputNumber
Overview
A numeric input field that only accepts numeric values, with increment/decrement controls, keyboard interaction, and min/max boundary handling. Use it for quantities, prices, ages, or any value that must stay numeric and within a range. For general text use SInput.
Usage
Features
- 📏 6 sizes: xs, sm, md, lg, xl, 2xl
- 🎚 Step buttons with press-and-hold acceleration (400ms → 60ms loop)
- ⌨️ Full keyboard support — Arrow keys, Page Up/Down, Home/End, Enter, wheel
- ⚖️
min/maxclamping with disabled buttons at boundaries,step,formatOptionsprecision - 🌐 Locale-aware formatting via
Intl.NumberFormat - 🧹 Clearable mode with an i18n
aria-labelclear button - 📋 Native form submission via a proxied hidden input when
nameis set - ♿ Full accessibility support —
aria-valuemin/max/now, clear naming, axe-clean
Demos
Basic
Slot
API
Aria Layer
7InputNumber
Props
| Prop | Type | Default | Description |
|---|---|---|---|
class | ClassValue | — | Additional class names applied to the root element. |
size | ThemeSize | — | Visual size of the component. |
ui | Partial<InputNumberUi> | — | Per-slot class overrides for the component. |
center | boolean | false | Whether to center the input. |
clearable | boolean | false | Whether to show the clear trigger. |
inputRef | ((el: HTMLInputElement) => void) | — | The function to set the input element. |
controlProps | InputNumberControlProps | — | Properties forwarded to the control element. |
incrementProps | InputNumberIncrementProps | — | Properties forwarded to the increment element. |
decrementProps | InputNumberDecrementProps | — | Properties forwarded to the decrement element. |
clearProps | ButtonProps | — | Properties forwarded to the clear element. |
defaultValue | number | — | The default value of the input |
modelValue | number | null | — | The controlled value of the input |
min | number | — | The smallest value allowed for the input. |
max | number | — | The largest value allowed for the input. |
step | number | — | The amount that the input value changes with each increment or decrement "tick". |
stepSnapping | boolean | — | When `false`, prevents the value from snapping to the nearest increment of the step value |
focusOnChange | boolean | — | When `true`, the input will be focused when the value changes. |
formatOptions | NumberFormatOptions | — | Formatting options for the value displayed in the number field. This also affects what characters are allowed to be
typed by the user. |
locale | string | — | The locale to use for formatting dates |
disableWheelChange | boolean | — | When `true`, prevents the value from changing on wheel scroll. |
invertWheelChange | boolean | — | When `true`, inverts the direction of the wheel change. |
rootProps | BaseProps | — | Properties forwarded to the root element. |
name | string | — | The name of the field. Submitted with its owning form as part of a name/value pair. |
required | boolean | — | When `true`, indicates that the user must set the value before the owning form can be submitted. |
id | string | — | Id of the input element |
autofocus | boolean | — | When `true`, the input is auto-focused. |
autocomplete | 'search' | 'name' | 'email' | 'tel' | 'url' | 'on' | 'off' | 'username' | 'current-password' | 'new-password' | 'one-time-code' | 'given-name' | 'family-name' | 'organization' | 'street-address' | 'address-level2' | 'postal-code' | 'country' | 'cc-name' | 'cc-number' | 'cc-exp' | 'cc-csc' | 'transaction-amount' | — | The autocomplete attribute of the input.
Supports the HTML autofill tokens (including password-manager values such as
`current-password` / `new-password`), in addition to the `on` / `off` switches. |
disabled | boolean | — | When `true`, prevents the user from interacting with the input. |
maxlength | number | — | The maximum number of characters allowed in the input |
minlength | number | — | The minimum number of characters allowed in the input |
pattern | string | — | The pattern attribute of the input |
placeholder | string | — | The placeholder of the input |
readonly | boolean | — | When `true`, the input is read-only. |
type | InputTypeHTMLAttribute | — | The type of the input element. |
Emits
| Emit Name | Parameters | Description |
|---|---|---|
update:modelValue | number | null | Emitted when the model value changes. |
clear | PointerEvent | Emitted when the clear button is clicked. |
Slots
| Slot Name | Parameters | Description |
|---|---|---|
leading | InputNumberCompactSlotProps | Custom content for the leading slot. |
trailing | InputNumberCompactSlotProps | Custom content for the trailing slot. |
clear | InputNumberCompactSlotProps | Custom content for the clear slot. |
decrement | InputNumberCompactSlotProps | Custom content for the decrement slot. |
increment | InputNumberCompactSlotProps | Custom content for the increment slot. |
InputNumberClear
Props
| Prop | Type | Default | Description |
|---|---|---|---|
type | ButtonType | 'button' | The type of the button element. Can be one of 'button', 'submit', or 'reset'. |
disabled | boolean | — | Whether the component is disabled. |
asChild | boolean | — | Change the default rendered element for the one passed as a child, merging their props and behavior. |
as | AsTag | Component | 'div' | The element or component this component should render as. Can be overwrite by `asChild` |
Emits
| Emit Name | Parameters | Description |
|---|---|---|
clear | PointerEvent | Emitted when the clear button is clicked. |
InputNumberCompact
Props
| Prop | Type | Default | Description |
|---|---|---|---|
clearable | boolean | false | Whether to show the clear trigger. |
inputRef | ((el: HTMLInputElement) => void) | — | The function to set the input element. |
controlProps | InputNumberControlProps | — | Properties forwarded to the control element. |
incrementProps | InputNumberIncrementProps | — | Properties forwarded to the increment element. |
decrementProps | InputNumberDecrementProps | — | Properties forwarded to the decrement element. |
clearProps | ButtonProps | — | Properties forwarded to the clear element. |
defaultValue | number | — | The default value of the input |
modelValue | number | null | — | The controlled value of the input |
min | number | — | The smallest value allowed for the input. |
max | number | — | The largest value allowed for the input. |
step | number | — | The amount that the input value changes with each increment or decrement "tick". |
stepSnapping | boolean | — | When `false`, prevents the value from snapping to the nearest increment of the step value |
focusOnChange | boolean | — | When `true`, the input will be focused when the value changes. |
formatOptions | NumberFormatOptions | — | Formatting options for the value displayed in the number field. This also affects what characters are allowed to be
typed by the user. |
locale | string | — | The locale to use for formatting dates |
disableWheelChange | boolean | — | When `true`, prevents the value from changing on wheel scroll. |
invertWheelChange | boolean | — | When `true`, inverts the direction of the wheel change. |
rootProps | BaseProps | — | Properties forwarded to the root element. |
name | string | — | The name of the field. Submitted with its owning form as part of a name/value pair. |
required | boolean | — | When `true`, indicates that the user must set the value before the owning form can be submitted. |
id | string | — | Id of the input element |
autofocus | boolean | — | When `true`, the input is auto-focused. |
autocomplete | 'search' | 'name' | 'email' | 'tel' | 'url' | 'on' | 'off' | 'username' | 'current-password' | 'new-password' | 'one-time-code' | 'given-name' | 'family-name' | 'organization' | 'street-address' | 'address-level2' | 'postal-code' | 'country' | 'cc-name' | 'cc-number' | 'cc-exp' | 'cc-csc' | 'transaction-amount' | — | The autocomplete attribute of the input.
Supports the HTML autofill tokens (including password-manager values such as
`current-password` / `new-password`), in addition to the `on` / `off` switches. |
disabled | boolean | — | When `true`, prevents the user from interacting with the input. |
maxlength | number | — | The maximum number of characters allowed in the input |
minlength | number | — | The minimum number of characters allowed in the input |
pattern | string | — | The pattern attribute of the input |
placeholder | string | — | The placeholder of the input |
readonly | boolean | — | When `true`, the input is read-only. |
type | InputTypeHTMLAttribute | — | The type of the input element. |
Emits
| Emit Name | Parameters | Description |
|---|---|---|
update:modelValue | number | null | Emitted when the model value changes. |
clear | PointerEvent | Emitted when the clear button is clicked. |
Slots
| Slot Name | Parameters | Description |
|---|---|---|
leading | InputNumberCompactSlotProps | Custom content for the leading slot. |
trailing | InputNumberCompactSlotProps | Custom content for the trailing slot. |
clear | InputNumberCompactSlotProps | Custom content for the clear slot. |
decrement | InputNumberCompactSlotProps | Custom content for the decrement slot. |
increment | InputNumberCompactSlotProps | Custom content for the increment slot. |
InputNumberControl
InputNumberDecrement
Props
| Prop | Type | Default | Description |
|---|---|---|---|
type | ButtonType | 'button' | The type of the button element. Can be one of 'button', 'submit', or 'reset'. |
disabled | boolean | — | Whether the component is disabled. |
asChild | boolean | — | Change the default rendered element for the one passed as a child, merging their props and behavior. |
as | AsTag | Component | 'div' | The element or component this component should render as. Can be overwrite by `asChild` |
InputNumberIncrement
Props
| Prop | Type | Default | Description |
|---|---|---|---|
type | ButtonType | 'button' | The type of the button element. Can be one of 'button', 'submit', or 'reset'. |
disabled | boolean | — | Whether the component is disabled. |
asChild | boolean | — | Change the default rendered element for the one passed as a child, merging their props and behavior. |
as | AsTag | Component | 'div' | The element or component this component should render as. Can be overwrite by `asChild` |
InputNumberRoot
Props
| Prop | Type | Default | Description |
|---|---|---|---|
defaultValue | number | — | The default value of the input |
modelValue | number | null | — | The controlled value of the input |
min | number | — | The smallest value allowed for the input. |
max | number | — | The largest value allowed for the input. |
step | number | — | The amount that the input value changes with each increment or decrement "tick". |
stepSnapping | boolean | — | When `false`, prevents the value from snapping to the nearest increment of the step value |
focusOnChange | boolean | — | When `true`, the input will be focused when the value changes. |
formatOptions | NumberFormatOptions | — | Formatting options for the value displayed in the number field. This also affects what characters are allowed to be
typed by the user. |
locale | string | — | The locale to use for formatting dates |
disableWheelChange | boolean | — | When `true`, prevents the value from changing on wheel scroll. |
invertWheelChange | boolean | — | When `true`, inverts the direction of the wheel change. |
rootProps | BaseProps | — | Properties forwarded to the root element. |
name | string | — | The name of the field. Submitted with its owning form as part of a name/value pair. |
required | boolean | — | When `true`, indicates that the user must set the value before the owning form can be submitted. |
id | string | — | Id of the input element |
autofocus | boolean | — | When `true`, the input is auto-focused. |
autocomplete | 'search' | 'name' | 'email' | 'tel' | 'url' | 'on' | 'off' | 'username' | 'current-password' | 'new-password' | 'one-time-code' | 'given-name' | 'family-name' | 'organization' | 'street-address' | 'address-level2' | 'postal-code' | 'country' | 'cc-name' | 'cc-number' | 'cc-exp' | 'cc-csc' | 'transaction-amount' | — | The autocomplete attribute of the input.
Supports the HTML autofill tokens (including password-manager values such as
`current-password` / `new-password`), in addition to the `on` / `off` switches. |
disabled | boolean | — | When `true`, prevents the user from interacting with the input. |
maxlength | number | — | The maximum number of characters allowed in the input |
minlength | number | — | The minimum number of characters allowed in the input |
pattern | string | — | The pattern attribute of the input |
placeholder | string | — | The placeholder of the input |
readonly | boolean | — | When `true`, the input is read-only. |
type | InputTypeHTMLAttribute | — | The type of the input element. |
Emits
| Emit Name | Parameters | Description |
|---|---|---|
update:modelValue | number | null | Emitted when the model value changes. |
Notes
Architecture and benchmark differences
VeanUI splits the input-number into an Aria layer (@vean/aria/input-number) that owns state, number parsing/formatting, boundary logic, and form proxying, and a styled layer (@vean/ui) that owns variants and UnoCSS classes. The Aria InputNumberCompact composes InputNumberRoot / InputNumberControl / InputNumberIncrement / InputNumberDecrement / InputNumberClear and exposes increment / decrement / clear slots. This mirrors the Aria/styled split and differs from single-package libraries such as Ant Design, Element Plus, and Mantine.
| Capability | VeanUI | Ant Design InputNumber | Element Plus input-number | Mantine NumberInput |
|---|---|---|---|---|
| Aria/styled split | ✅ | — | — | — |
| Controlled / uncontrolled | ✅ | ✅ | ✅ | ✅ |
| step / min / max / precision | ✅ | ✅ | ✅ | ✅ |
| Keyboard Arrow/Page/Home/End | ✅ | ✅ | ✅ | ✅ |
| Press-and-hold acceleration | ✅ | ✅ | — | — |
| Boundary button disabling | ✅ | — | ✅ | — |
Clear button (i18n aria-label) | ✅ | — | ✅ | — |
| Locale-aware format (Intl) | ✅ | — | — | — |
| Size variants (xs…2xl) | ✅ | — | — | ✅ |
center layout | ✅ | ✅ | ✅ | — |
Cautions
formatter/parserhooks,controlsvisibility toggle, andcompactmode are not implemented; they are tracked as enhancement backlog.- While a value is actively typed, the component accepts intermediate states and snaps back to a valid number on blur / Enter.
- The clear button only appears on hover or focus (desktop convention).
FAQ
How do I restrict the input to a numeric range?
Pass min and max. Values are clamped on change, and the increment/decrement buttons are disabled at the boundaries.
How do I control the number of decimal places?
Control the number of decimal places via formatOptions.maximumFractionDigits (for example { maximumFractionDigits: 2 }). Formatting and step calculation respect the configured precision.
How does keyboard entry work?
Arrow Up/Down step by step; Page Up/Down step by step * 10; Home/End jump to min/max; Enter commits; the mouse wheel adjusts the value when hovered.
How do I localize the displayed number?
The component uses Intl.NumberFormat with the active locale (and any formatOptions). Thousands separators and decimal marks follow the locale automatically.