Quantity Stepper

Holds suspicious quantity jumps for a "Did you mean 10?" check and clamps to stock with a reason, so an accidental bulk order isn't placed.

StopsAccidental bulk order

Installation

pnpm dlx shadcn@latest add https://bollard-ui.vercel.app/r/quantity-stepper.json

The files land in your project. They're yours to edit.

Usage

quantity-stepper-usage.tsx
import { QuantityStepper } from "@/components/ui/quantity-stepper"

<QuantityStepper label="Coffee beans, 250 g" value={cart} onValueChange={setCart} typical={2} max={500} stock={250} />

What it catches

  • Typed jumps far above the typical quantity (100 when people order 2)
  • Values over max or stock, clamped with a reason
  • Quantities that aren't a whole pack (step)
  • Scroll-wheel changes while scrolling the page

Props

QuantityStepper props
PropTypeDefault
label

Visible label.

string"Quantity"
value

Controlled quantity.

number—
defaultValue

Initial quantity when uncontrolled.

number—
onValueChange

Called with every committed quantity. Suspicious typed jumps wait for confirmation first.

(value: number) => void—
min

Lowest allowed quantity.

number1
max

Highest allowed quantity.

number99
stock

Units available; the effective maximum is the lower of `max` and `stock`.

number—
typical

What a typical order looks like. Typed values far above it ask for confirmation.

number—
step

Units per step (a pack size). Typed values snap to whole steps counted from `min`.

number1
soldOutMessage

Text shown when stock is below the minimum.

string—
decreaseLabel

Accessible labels of the − and + buttons.

string—
increaseLabel

Accessible label for the plus button.

string—
messages

Override any other user-visible string (see `QUANTITY_MESSAGES`).

Partial<QuantityMessages>—

* required. Also accepts the native props of <input> (className, aria-*, data-*…), passed through to it.

Accessibility

  • Visible label; the input is a spinbutton with min, max and now values, described by a hint
  • Enter commits a typed value
  • +/- buttons have aria-labels and aria-controls, and are skipped in tab order

Only what the source does. Test with your own screen reader and content before shipping.

Limitations

This is a UX guard rail. Enforce on the server: Validate quantity against live stock and order limits on the server.

  • "Suspicious" is relative to your typical prop
  • Stock shown is what you pass; it may be stale
  • Doesn't reserve stock

What it stops

Accidental bulk order

Also known as

quantity · stepper · qty · add to cart · cart · plus minus · number input · stock

Field type

Dependencies

Pairs well with