Bounds it can't leave.
min defaults to 1, max is open-ended, and
value starts at the minimum. Each button disables itself at its own bound —
typing out of range snaps back on commit.
Count by sixes.
step sets how much each press moves. Clamping still wins at the edges, so a
step that would overshoot lands on max instead.
Out of stock.
disabled on the host disables both buttons and the input, and every handler
no-ops. Toggle it as a property from JavaScript.
Enter commits. Nothing submits.
This is a real <form>. Type a quantity and press Enter — the value is
committed and the keypress is swallowed, so the form never implicitly submits. The button
still does.
Listen in.
Every committed change fires a bubbling quantity-input:change with
{ value }. Clamped input and no-op presses stay quiet.
One cart, many steppers.
Instances are fully independent — separate bounds, separate state. The subtotal listens once, on the list, because the event bubbles.
The whole API, on one screen.
Five attributes, all mirrored as properties, and one event. That's everything.
Attributes & Properties
min10 is validmaxnullvalueminstep1disabledfalseMarkup hooks & Events
[data-action-decrement][data-action-increment]inputquantity-input:change{ value }