InputNumber
InputNumber is a numeric field built on reka-ui's number field. It emits a number | null model, supports min / max / step / integer, and formats its value with Intl.NumberFormat (including currency and percent styles). Optional stepper buttons provide pointer-driven increments.
<script setup lang="ts">
import { ref } from 'vue'
import { InputNumber } from '@myghf/ui'
const quantity = ref<number | null>(1)
</script>
<template>
<InputNumber v-model="quantity" :min="0" :max="10" show-buttons />
</template>Examples
Bounds and stepper buttons
modelValue is number | null. Clearing the field (or entering a non-numeric value) emits null rather than NaN. showButtons adds keyboard-accessible increment and decrement controls.
<script setup lang="ts">
import { ref } from 'vue'
import { InputNumber } from '@myghf/ui'
const quantity = ref<number | null>(3)
</script>
<template>
<div class="grid max-w-xs gap-4">
<div class="grid gap-1.5">
<label class="text-sm font-medium text-foreground" for="demo-quantity">Quantity</label>
<InputNumber
id="demo-quantity"
v-model="quantity"
:min="0"
:max="10"
show-buttons
/>
</div>
<InputNumber
v-model="quantity"
placeholder="Empty is null"
aria-label="Quantity without stepper buttons"
/>
</div>
</template>Formatting
currency is shorthand for a currency Intl.NumberFormatOptions; formatOptions supplies the full options object (here a percent style); locale selects the format locale. stepSnapping rounds typed values to the nearest step.
<script setup lang="ts">
import { ref } from 'vue'
import { InputNumber } from '@myghf/ui'
const price = ref<number | null>(1250.5)
const ratio = ref<number | null>(0.75)
const weight = ref<number | null>(72.5)
</script>
<template>
<div class="grid max-w-xs gap-4">
<InputNumber v-model="price" currency="USD" locale="en-US" :min="0" aria-label="Price" />
<InputNumber
v-model="ratio"
locale="en-US"
:format-options="{ style: 'percent', maximumFractionDigits: 0 }"
aria-label="Ratio"
/>
<InputNumber
v-model="weight"
:step="0.25"
step-snapping
:min="0"
suffix="kg"
aria-label="Weight"
/>
</div>
</template>Props
| Prop | Type | Default | Description |
|---|---|---|---|
modelValue | number | null | — | Bound numeric value; null when empty. |
min | number | — | Minimum allowed value. |
max | number | — | Maximum allowed value. |
step | number | 1 | Increment/decrement size. A non-positive or non-finite value is normalised to 1 before it reaches the field. |
stepSnapping | boolean | false | Rounds typed values to the nearest multiple of step. |
integer | boolean | false | Forces zero fraction digits (maximumFractionDigits: 0). |
locale | string | — | BCP-47 locale for Intl.NumberFormat, and for the aria-valuetext readout. |
formatOptions | Intl.NumberFormatOptions | — | Full formatting options; merged over the currency shorthand, and integer is applied last. |
currency | string | — | Currency code (for example 'USD'); applies { style: 'currency' }. |
prefix | string | — | Decorative text rendered before the number (for example '$'). |
suffix | string | — | Decorative text rendered after the number (for example 'kg'). |
showButtons | boolean | false | Renders increment/decrement stepper buttons. |
placeholder | string | — | Placeholder text shown while empty. |
disabled | boolean | false | Disables the control. |
readonly | boolean | false | Makes the value read-only while still focusable. |
invalid | boolean | false | Applies the error styling and sets aria-invalid="true" on the input. |
size | 'sm' | 'default' | 'lg' | 'default' | Control height. |
id | string | — | Applied to the underlying input, so an external <label for> matches. |
name | string | — | Form field name for the underlying input. |
Events
| Event | Payload | Description |
|---|---|---|
update:modelValue | number | null | Emitted when the value changes. Empty or non-finite input collapses to null. |
Slots
InputNumber renders no slots. Use prefix / suffix for fixed adornments.
Exposed methods
None. InputNumber does not call defineExpose.
Accessibility
- The underlying field is a native input with
role="spinbutton", so screen readers announce it as a numeric control with arrow-key support from reka-ui. invalidsetsaria-invalid="true"on the input automatically.- When a value is present, the input exposes a locale-formatted
aria-valuetext(for example1,234.5), soIntlformatting is announced rather than the raw string. It is omitted when the field is empty. prefixandsuffixare plain sibling text, not part of the input. A screen reader may read them as loose text without associating them with the value. For a real unit, prefercurrency/formatOptions(which feedaria-valuetext) or include the unit in the field's<label>.- The stepper buttons rendered by
showButtonscome from reka-ui and are keyboard reachable; they are disabled automatically atmin/max.
Dark mode & RTL
- The wrapper uses semantic tokens (
bg-surface,text-foreground,border-border) and the invalid state useserror-500, so both themes are covered withoutdark:overrides. prefixandsuffixsit in a flex row and the stepper column uses logical margin (ms-1), so the layout mirrors under RTL. The prefix/suffix text is direction-neutral; numbers themselves are rendered left-to-right byIntlregardless of direction.