Design system Inputs
Stepper
Increment or decrement one small bounded count. The group owns the border; each end keeps the full target.
.mk-stepper
Overview
The stepper changes one small bounded count — adults, children, nights. The group owns the border, each end keeps a full 44px target, and the value sits centred in tabular numerals so it does not shiver between 1 and 11. Try it.
Usage
- Adjust a small bounded countUse a stepper for integer values with a meaningful minimum, maximum, and step of one.
- Make incremental changes faster than typingMinus and plus change the visible value immediately and become unavailable at their respective bounds.
- Use Text input for broad numeric entryAmounts, measurements, and values with large or irregular ranges should be typed and validated instead of stepped.
Anatomy
- 1The group. One border around the whole control — the boundary is the component's, not each button's. Hover and focus-within warm it.
- 2Minus control. A 44 × 44px button with no invisible expander: its visible seat is already the full target.
- 3The value. Centred, tabular numerals, stable width — the number the two ends argue about.
- 4Plus control. The matching 44 × 44px button increments the value. It has the same visible target and focus treatment as Minus.
Variants and states
One size — the 44px control height. A count that needs a denser face belongs to a different control.
States
Every state below is the real component wearing that state, not a picture of it.
| State | Specimen | What changes |
|---|---|---|
| Rest |
2
|
The strong grey edge on the group. |
| Hover |
2
|
The group border warms — the family's shared answer — and the end under the pointer takes the quiet band wash. |
| Keyboard focus |
2
|
The standard 2px camel outline, drawn inward on the focused end; focus-within warms the group border the same way hover does. |
| At a bound |
0
|
The blocked end takes aria-disabled and stays where it is.
It never disappears: a vanished minus teaches nothing about why the count
stops here. |
Do and don't
The field label names the count; the ends name it too, for the screen reader.
A bare number input for a three-step count trades two honest presses for a keyboard, spinners the UA draws its own way, and free text to validate.
Copy
- The ends say the objectThe accessible names are "Fewer adults" and "More adults" — not bare arithmetic.
- The bound explains itself nearbyWhy two is the floor is the row's sentence, not the control's.
Accessibility
- Real buttons at the endsEach has its own object-naming label.
- The value is announcedA live region speaks the new count after each press.
- Blocked, not removed
aria-disabledat the bounds keeps the end reachable and its reason learnable.
When to reach for something else
- An unbounded or large numberUse a numeric Text input — forty presses are not an interface.
- Choosing from named optionsUse Dropdown; a stepper's value has no names.
Markup
<div class="mk-stepper"> <button class="mk-stepper-btn" type="button" aria-label="Fewer adults">−</button> <span class="mk-stepper-value">2</span> <button class="mk-stepper-btn" type="button" aria-label="More adults">+</button> </div>