Number Input
A numeric stepper input with decrement and increment buttons flanking a central text field, supporting min/max clamping, step increments, and keyboard shortcuts.
<arc-number-input> Overview
>
NumberInput combines a native numeric text field with decrement and increment buttons to create a precise, user-friendly numeric stepper. The three elements are presented as a unified control with a shared border and rounded corners, where the buttons sit on either side of the input field separated by subtle inner borders. When the control receives focus, the entire border shifts to accent-primary with a focus ring, providing clear visual feedback.
The component enforces value boundaries through automatic clamping. When `min` or `max` props are set, the value is clamped to stay within range, and the corresponding button becomes disabled and visually dimmed when the limit is reached. The `step` prop controls the increment granularity for both button clicks and keyboard interactions. Holding Shift while pressing arrow keys multiplies the step by 10, enabling quick large adjustments without repeated clicks.
When a `label` is provided, it renders as an uppercase accent-font label above the control, connected to the input via a generated `id` and `for` attribute for accessibility. The events mirror the native control: typing fires `arc-input` alone on each keystroke, and the value commits with `arc-change` on blur or Enter. A stepper button click or an arrow key fires both, because each of those is an edit and a commit in one gesture. Every event carries the new value in its detail.Guidelines
When to use
- Use NumberInput when the user needs to enter or adjust an exact numeric value
- Set `min` and `max` to prevent invalid values and provide clear boundary feedback
- Choose a `step` that matches your data precision — 1 for integers, 0.1 for decimals
- Provide a `label` so the input is properly announced by screen readers
- Use the Shift+Arrow shortcut tip in help text for power users who need fast adjustments
When not to use
- Do not use NumberInput for approximate values or large ranges — use Slider instead
- Do not omit `min` and `max` when there are logical boundaries for the value
- Do not set a `step` of 0 — it prevents the buttons from changing the value
- Do not use NumberInput for non-numeric data like phone numbers — use a standard Input with a pattern
- Avoid stacking many number inputs without labels — each one needs context for usability
Features
- Inline decrement and increment buttons flanking a centered numeric text field
- Automatic value clamping to `min` and `max` boundaries with buttons disabled at limits
- Configurable `step` for increment granularity, with Shift+Arrow for 10x step multiplier
- Focus-within styling applies accent-primary border and ring to the entire control group
- Label rendered as uppercase accent-font text above the control with proper `for` association
- Native `spinbutton` ARIA role with `aria-valuenow`, `aria-valuemin`, and `aria-valuemax`
- Hides browser-native spin buttons for a clean cross-platform appearance
- Disabled state at 40% opacity with pointer events blocked
Preview
Usage
This component requires JavaScript. No pure HTML/CSS version is available — use the Web Component directly or a framework wrapper.
<arc-number-input label="Quantity" value="3" min="1" max="99" step="1"></arc-number-input> import { NumberInput } from '@arclux/arc-ui-react';
export default function Example() {
return (
<NumberInput label="Quantity" value={3} min={1} max={99} step={1} />
);
} <script setup>
import { NumberInput } from '@arclux/arc-ui-vue';
</script>
<template>
<NumberInput label="Quantity" :value="3" :min="1" :max="99" :step="1" />
</template> <script>
import { NumberInput } from '@arclux/arc-ui-svelte';
</script>
<NumberInput label="Quantity" value={3} min={1} max={99} step={1} /> import { Component } from '@angular/core';
import { NumberInput } from '@arclux/arc-ui-angular';
@Component({
imports: [NumberInput],
template: `
<arc-number-input label="Quantity" [value]="3" [min]="1" [max]="99" [step]="1"></arc-number-input>
`,
})
export class MyComponent {} import { NumberInput } from '@arclux/arc-ui-solid';
export default function Example() {
return (
<NumberInput label="Quantity" value={3} min={1} max={99} step={1} />
);
} import { NumberInput } from '@arclux/arc-ui-preact';
export default function Example() {
return (
<NumberInput label="Quantity" value={3} min={1} max={99} step={1} />
);
} API
-
size'sm' | 'md' | 'lg''md' - Control size. `md` is the default; `sm` and `lg` scale the field padding.
-
valuenumber0 - Current numeric value. Reflected as an attribute and updated on user interaction.
-
minnumberundefined - Minimum allowed value. The decrement button is disabled when the value reaches this limit.
-
maxnumberundefined - Maximum allowed value. The increment button is disabled when the value reaches this limit.
-
stepnumber1 - Increment and decrement step size. Arrow keys use this value, Shift+Arrow uses 10x this value.
-
labelstring'' - Label text displayed above the control in uppercase accent font.
-
namestring'' -
disabledbooleanfalse - Disables interaction, reducing opacity to 40% and blocking pointer events.
-
readonlybooleanfalse - Prevents value changes from typing, stepper buttons, and arrow keys while keeping the field focusable and its value submitted.
-
formAssociatedbooleantrue -
propertiesobject{ required: { type: Boolean, reflect: true }, readonly: { type: Boolean, reflect: true }, } - Lit merges static properties up the prototype chain, so every consumer gets these without declaring them. `required` participates in constraint validation below; `readonly` reflects for styling and is enforced by each component's interaction handlers (the mixin can't know which gestures mutate state).
-
autoValidatesbooleantrue - Components that run their own constraint-validation logic (pattern checks, range checks) opt out of the automatic required sync by overriding this to false, and own the whole validity flag set instead.
-
form -
validity -
validationMessage -
requiredbooleanfalse
Events
-
arc-inputdetail: { value: number } - Fired on every edit, including each keystroke while typing. Use for live previews.
-
arc-changedetail: { value: number } - Fired when the value is committed: blur or Enter after typing, or immediately on a stepper click or arrow key, which are edit and commit in one gesture.
See Also
- Input Versatile form control supporting single-line text, email, password, and multiline textarea modes with built-in label, placeholder, and validation states. Pairs with Form for complete data-entry workflows.
- Slider Range input slider with a label, live numeric value display, accent-primary fill track, and customisable min/max/step.