Components / Forms

NumberInput

A native number field with step buttons and optional units.

Preview

Use cases

Bounded quantities

Let shoppers type a quantity or use step buttons within inventory limits.

Measurements

Display a unit beside a fractional numeric value without storing the unit in the model.

Usage example

Vue
<script setup lang="ts">
import { ref } from 'vue'
import NumberInput from './components/ui/number-input/NumberInput.vue'
const weight = ref<number | undefined>(2.5)
const messages = { decrement: 'Decrease', increment: 'Increase' }
</script>

<template>
  <NumberInput v-model="weight" :min="0" :step="0.25" :messages="messages" wheel>
    <template #suffix>kg</template>
  </NumberInput>
</template>

More examples

Ticket count

A whole-number quantity with explicit bounds.

Ticket count
<script setup lang="ts">
import { ref } from 'vue'
import NumberInput from './components/ui/number-input/NumberInput.vue'
const tickets = ref<number | undefined>(1)
const messages = { decrement: 'Fewer tickets', increment: 'More tickets' }
</script>
<template>
  <label for="tickets">Tickets</label>
  <NumberInput id="tickets" v-model="tickets" name="tickets" :min="1" :max="8" :step="1" :messages="messages" />
</template>

Weight in kilograms

An explicit minimum anchors the quarter-step grid.

Weight in kilograms
<script setup lang="ts">
import { ref } from 'vue'
import NumberInput from './components/ui/number-input/NumberInput.vue'
const weight = ref<number | undefined>(0.5)
const messages = { decrement: 'Decrease weight', increment: 'Increase weight' }
</script>
<template>
  <label for="weight">Weight in kilograms</label>
  <NumberInput id="weight" v-model="weight" :min="0" :max="20" :step="0.25" :messages="messages">
    <template #suffix>kg</template>
  </NumberInput>
</template>

Key API

The most useful props, models, slots, events, and methods for this component.

Key API for NumberInput
NameTypeDefault or requirement
v-modelnumber | undefinedundefined
messages{ increment: string; decrement: string }required
min / max / stepnumberunbounded / 1
wheelbooleanfalse
disabled / readonly / invalidbooleanfalse

Arrow keys and buttons step the value. Opt in with wheel to let a focused input step on vertical scrolling; unfocused fields keep page scrolling.

Implementation notes

  • Clearing the field emits undefined; handle that state before calculating totals.
  • Typed invalid values remain editable. Check native validity on submit rather than assuming the step buttons enforce typed input.

Accessibility and localization

  • Pass localized increment and decrement labels through messages. Mention units in the label or description, not only in the suffix.
Weini UIDesign system · Vue component library · Free and public