NumberField
A number field is a text field that knows it holds a number. It parses what is typed against the reader's locale, clamps to the range, and formats the result when the field loses focus — so 1,024 and 1.024 both mean what the reader meant by them.
import { NumberField, NumberFieldGroup, NumberFieldInput } from "ropav";<NumberField class="w-48" :default-value="1024" name="width">
<Label>Width</Label>
<NumberFieldGroup>
<NumberFieldDecrementButton />
<NumberFieldInput />
<NumberFieldIncrementButton />
</NumberFieldGroup>
</NumberField>Steppers and formatting
format-options is passed straight to Intl.NumberFormat, so a percentage, a currency or a unit is a matter of describing it rather than of formatting it yourself.
number-field-basic.vue
<script setup lang="ts">
import {
Label,
NumberField,
NumberFieldDecrementButton,
NumberFieldGroup,
NumberFieldIncrementButton,
NumberFieldInput,
} from "ropav";
</script>
<template>
<div class="stack">
<NumberField class="field" :default-value="1024" :min-value="0" name="width">
<Label>Width</Label>
<NumberFieldGroup>
<NumberFieldDecrementButton />
<NumberFieldInput />
<NumberFieldIncrementButton />
</NumberFieldGroup>
</NumberField>
<NumberField
class="field"
:default-value="0.15"
:format-options="{ style: 'percent' }"
name="rate"
:step="0.01"
>
<Label>Rate</Label>
<NumberFieldGroup>
<NumberFieldDecrementButton />
<NumberFieldInput />
<NumberFieldIncrementButton />
</NumberFieldGroup>
</NumberField>
</div>
</template>
<style scoped>
.stack {
display: flex;
flex-direction: column;
gap: calc(var(--rp-spacing) * 4);
}
.field {
width: calc(var(--rp-spacing) * 48);
}
</style>step decides what the steppers and the arrow keys move by, and it is also what the value is snapped to.
Locale
The field reads its locale from the nearest I18nProvider, falling back to the browser's. Pin it with locale when the number has to be read the same way everywhere — a code, an identifier, anything that is a number by type but not by meaning.
Accessibility
- The steppers are real buttons with their own labels, so they are reachable and announced.
- Arrow keys step the value while the input is focused; Page Up and Page Down take larger steps.
is-wheel-disabledstops the scroll wheel changing the value, which is worth setting for a field inside a scrolling panel.
API
NumberField
| Prop | Type | Default | Description |
|---|---|---|---|
ariaDescribedby | string | — | |
ariaLabel | string | — | Accessible name, for a field with no visible label. |
ariaLabelledby | string | — | |
autoFocus | boolean | — | Whether the field takes focus on mount. |
commitBehavior | "snap" | "validate" | "snap" | What happens to the value once the user is done editing. "snap" pulls it into range and onto a step; "validate" leaves it and lets validation object. |
decrementAriaLabel | string | — | Overrides the name the decrement button announces. |
defaultValue | number | — | The number the field starts with, and goes back to when the form is reset. |
form | string | — | id of the form to submit with, for a field rendered outside it. |
formatOptions | Intl.NumberFormatOptions | — | How the number is written, and by extension which characters may be typed. |
fullWidth | boolean | — | Whether the field stretches to fill its container. |
id | string | — | Lands on the control, which is the field as far as assistive technology is concerned. |
incrementAriaLabel | string | — | Overrides the name the increment button announces. |
isDisabled | boolean | — | Whether the field is disabled — no interaction, no submission. |
isInvalid | boolean | — | Whether the value fails validation. Setting it either way takes the field over: false claims the field is valid and shadows validate, the browser and the server alike. |
isReadOnly | boolean | — | Whether the number can be read but not changed. |
isRequired | boolean | — | Whether the field has to be filled in for the form to submit. |
isWheelDisabled | boolean | — | Whether the wheel over a focused field is ignored. |
locale | string | — | Locale the number is written and read in. Defaults to the runtime's own. |
maxValue | number | — | |
minValue | number | — | |
name | string | — | Name submitted with the form. |
size | "xs" | "sm" | "md" | "lg" | "md" | How tall the field stands, matching a button of the same size. |
step | number | 1, or 0.01 for a percentage | How far one step moves the value. |
validate | ValidationFunction<number> | — | Checks the number and returns a message when it is not acceptable. |
validationBehavior | "aria" | "native" | "native" | How the field reports validation. Inherited from the surrounding form when unset. |
value | number | null | — | The number in the field. Makes it controlled. null means no number at all. |
variant | "primary" | "secondary" | "primary" | Visual variant. |
The default slot receives:
| Slot prop | Type |
|---|---|
isDisabled | boolean |
isInvalid | boolean |
isReadOnly | boolean |
isRequired | boolean |
numberValue | number |
validationDetails | ValidationDetails |
validationErrors | string[] |
| Event | Payload |
|---|---|
change | number |
focusChange | boolean |
update:value | number |
NumberFieldDecrementButton
Slots: default.
NumberFieldGroup
The default slot receives:
| Slot prop | Type |
|---|---|
isDisabled | boolean |
isFocusWithin | boolean |
isHovered | boolean |
isInvalid | boolean |
NumberFieldIncrementButton
Slots: default.
NumberFieldInput
| Prop | Type | Default | Description |
|---|---|---|---|
placeholder | string | — |