The number input wraps a native <input type="number"> with decrement and increment buttons for easier interaction. It respects min, max, and step attributes.
Basic usage
<div class="number-input" role="group" aria-label="Quantity">
<button class="number-input-btn" data-number-decrement type="button" aria-label="Decrease">−</button>
<input type="number" value="1" min="0" max="99" aria-label="Quantity">
<button class="number-input-btn" data-number-increment type="button" aria-label="Increase">+</button>
</div>
With min, max, and step
<input type="number" value="10" min="0" max="100" step="5">
Disabled
JavaScript
Include assets/js/number-input.js on any page. The script handles all [data-number-increment] and [data-number-decrement] buttons via event delegation.
<script src="/assets/js/number-input.js"></script>
Accessibility notes
- Wrap in
role="group"witharia-labeldescribing the input - Each button needs
aria-label("Increase" / "Decrease") - The native
<input type="number">handles value announcements min,max,stepare respected by the JS and exposed to assistive technology
Styling
The control is one field with two steppers on it, not three controls in a row. The border and the --radius-s corner belong to the whole thing; the steppers are transparent until pointed at, so the field reads as the subject and the buttons as affordances on it.
The value is set in tabular figures. Without them the field reflows as the number steps through digits of different widths, and the whole control shifts on every click.
Inside a bar it takes the bar's control height and a fixed 4.5rem field, so a four-digit value cannot resize the bar around it.
Do / Don't
Do:
- Use number inputs for small, precise quantities (1-99)
- Always set
minandmaxto prevent invalid values - Pair with a
<label>for context
Don't:
- Don't use for large numeric ranges. Use a slider instead
- Don't use for values that aren't truly numeric (e.g. phone numbers)
Use in another product
The design system installs once per product:
npm install github:bydefaultstudio/design-system-dist#semver:^4.7.0
This component's styles ship in design-system.css. Its behaviour ships as dist/js/number-input.js — copy it into the product's served assets and include it once per page:
<script src="assets/js/number-input.js" defer></script>