Number Field
Installation
npx @mielui/svelte add number-fieldyarn dlx @mielui/svelte add number-fieldbunx @mielui/svelte add number-fieldUsage
NumberField keeps one native number input as the form control. Put name, form, min, max, step, required, disabled, and readonly on Root, and bind value to a number. Clearing the input sets it to undefined.
Native validation reports missing values, bounds, and step mismatches; typing never clamps a value silently. The arrow keys and the step buttons follow the browser's step rules and stop at the bounds, and an invalid step falls back to 1. The wheel is left alone. Format read-only totals with Intl.NumberFormat; the field does not format currency.
Label and Input share an id; set inputId on Root to choose it. If you set id on Input yourself, also set for on Label, or name the input with Field.Control. Pass descriptions and errors to Input. With a SvelteKit remote form, put the field name on Root, pass the current number as value, and update it in onValueChange.
<script lang="ts">
import * as NumberField from '@mielui/svelte/components/number-field';
let seats = $state<number | undefined>(2);
</script>
<NumberField.Root bind:value={seats} min={1} max={12}>
<NumberField.Label>Seats</NumberField.Label>
<NumberField.Group>
<NumberField.Decrement />
<NumberField.Input />
<NumberField.Increment />
</NumberField.Group>
</NumberField.Root>Examples
Decimal steps
A step of 0.25 with both buttons after the input. Each stepper takes its own aria-label.
Form submission and reset
Disabled
Parts
Root renders its children, so you choose the order of the input and the two buttons, and the input keeps working when a button is left out. Root, Input, Decrement, and Increment take bind:element, for example to focus the input after a reset. Decrement and Increment take onclick, which runs before the value steps; call preventDefault() there to cancel the step.
Labels
Pass labels to Root to translate the accessible names of the two step buttons. Every key of NumberFieldLabels is optional; omitted keys keep the English text. An aria-label on a button wins.
<script lang="ts">
import * as NumberField from '@mielui/svelte/components/number-field';
import type { NumberFieldLabels } from '@mielui/svelte/components/number-field';
const labels: NumberFieldLabels = {
decrease: 'Diminuer',
increase: 'Augmenter'
};
</script>
<NumberField.Root {labels}>
<NumberField.Label>Places</NumberField.Label>
<NumberField.Group>
<NumberField.Decrement />
<NumberField.Input />
<NumberField.Increment />
</NumberField.Group>
</NumberField.Root>API reference
NumberField.Root
labelsNumberFieldLabelsOverrides the built-in text and accessible names. Every key is optional and English is the fallback.
valueBindablenumberCurrent number. Bindable.
inputIdstringId of the input, for a label outside the field.
minnumberSmallest allowed value.
maxnumberLargest allowed value.
stepnumberAmount each step changes the value by.
Default
1namestringField name submitted with the form.
formstringId of the form this control belongs to when it sits outside that form.
disabledbooleanPrevents interaction and dims the control.
Default
falsereadonlybooleanShows the value without allowing edits. The value is still submitted.
Default
falserequiredbooleanRequires a value before the form can be submitted.
Default
falseonValueChange((value: number | undefined) => void)Called with the new value when it changes.
childrenSnippet<[{ value: number | undefined; }]>Content rendered inside.
elementBindableHTMLDivElementBindable reference to the DOM element.
NumberField.Decrement
onclick((event: MouseEvent) => void)Called on click, before the value steps. Call
preventDefault()to skip the step.elementBindableHTMLButtonElementBindable reference to the DOM element.
NumberField.Increment
onclick((event: MouseEvent) => void)Called on click, before the value steps. Call
preventDefault()to skip the step.elementBindableHTMLButtonElementBindable reference to the DOM element.
NumberField.Input
elementBindableHTMLInputElementBindable reference to the DOM element.
Other parts
These parts have no props of their own. They pass HTML attributes and events to their element.
NumberField.GroupNumberField.Label
pnpm dlx @mielui/svelte add number-field