Number Input
A numeric input with increment and decrement buttons. Constrains input to numbers within an optional range.
Preview
Sizes
States
Minimum quantity is 1.
Features
- Increment/decrement buttons for mouse and touch users.
- Native
<input type="number">for keyboard support (arrow keys, direct typing). - Browser spin buttons hidden — custom buttons provide consistent appearance.
- Focus ring wraps the entire composite control.
States
| State | Appearance |
|---|---|
| Default | Buttons flanking the number field |
| Focus | Brand-purple border with focus shadow around the entire control |
| Hover (button) | Button background shift |
| Disabled | Reduced opacity, no interaction |
| Error | Red border with error message |
Props
| Prop | Type | Default | Description |
|---|---|---|---|
value | number | -- | Current value |
onChange | (value: number) => void | -- | Change handler |
min | number | -- | Minimum allowed value |
max | number | -- | Maximum allowed value |
step | number | 1 | Increment step |
size | 'sm' | 'md' | 'lg' | 'md' | Input size |
disabled | boolean | false | Disables the input |
error | string | -- | Error message |
label | string | -- | Visible label |
Code example
React
tsx
import { NumberInput } from '@thepace/lexicon/components';
<NumberInput label="Quantity" value={qty} onChange={setQty}
min={1} max={99} />Vanilla HTML
html
<div class="lex-input-wrapper">
<label class="lex-input__label">Quantity</label>
<div class="lex-number-input lex-number-input--md">
<button class="lex-number-input__btn" aria-label="Decrease">−</button>
<input type="number" class="lex-number-input__field"
value="3" min="1" max="99" />
<button class="lex-number-input__btn" aria-label="Increase">+</button>
</div>
</div>CSS class reference
| Class | Purpose |
|---|---|
.lex-number-input | Composite container |
.lex-number-input__field | The number input |
.lex-number-input__btn | Increment/decrement button |
.lex-number-input--sm | Small size |
.lex-number-input--md | Medium size |
.lex-number-input--lg | Large size |
.lex-number-input--disabled | Disabled state |
.lex-number-input--error | Error state |
Accessibility
- Buttons have
aria-label("Increase" / "Decrease"). - Native
<input type="number">handles keyboard arrow key increments. - When min/max is reached, the corresponding button should be disabled and set
aria-disabled="true". - Focus ring wraps the entire composite control via
:focus-within.
Guidelines
Do
- Set clear
minandmaxboundaries and communicate them. - Disable the decrement button at min and increment at max.
Don't
- Don't use for free-form numeric entry — use a standard Input with
type="number". - Don't omit
aria-labelon the increment/decrement buttons.