Skip to content

shadcn.io is an independent project built on shadcn/ui

Quantity Picker Button Group for React

Minus and plus around a count, starting at 1 and at Qty: 5, with minus disabled when the count is zero.

Plus and minus around a count. The first picker starts at 1. The second starts at 5 and reads Qty: 5. Minus turns off at zero, so the buttons cannot go negative. There is no field to type a number.

Use it beside a product in a cart. If people must type the quantity, use Number Input, which also steps and limits the value. In React, Base UI does not cap how high the count can go.

Preview

Preview width

Installation

Sign in to get your install command
Free with an account. It carries your token, so the CLI installs everything in one go.
Use email insteadNo credit card

Anatomy

Button Group anatomy: root, group, button, separator

Usage

<div className="flex flex-col gap-4">
  <ButtonGroup aria-label="Quantity">
    <Button
      aria-label="Decrease quantity"
      disabled={quantity1 === 0}
      onClick={decrement1}
      size="icon-sm"
      variant="outline"
    >
      <MinusIcon aria-hidden="true" />
    </Button>
    <ButtonGroupText aria-live="polite" className="min-w-12 justify-center">
      {quantity1}
    </ButtonGroupText>
    <Button
      aria-label="Increase quantity"
      onClick={increment1}
      size="icon-sm"
      variant="outline"
    >
      <PlusIcon aria-hidden="true" />
    </Button>
  </ButtonGroup>
  <ButtonGroup aria-label="Quantity">
    <Button
      aria-label="Decrease quantity"
      disabled={quantity2 === 0}
      onClick={decrement2}
      size="icon-sm"
      variant="outline"
    >
{/* The rest of the file is under Installation. */}

FAQ

How are the two quantities tracked?

Each picker has its own value, 1 and 5. Minus subtracts one, never below 0, and plus adds one with no upper limit.

When is minus disabled?

When that quantity is 0. The minus Button gets disabled from that check.

How are the icon buttons named?

Each has an aria-label, Decrease quantity or Increase quantity, and size="icon-sm". The icons have aria-hidden="true".

Is the new count announced?

Yes. The ButtonGroupText has aria-live="polite", so a screen reader reads the number after it changes.

Can people type a number?

Not here; the count is text. The Stepper Button Group puts an input between the buttons, and Number Input handles typing, limits and steps in one component.

How do I cap the quantity?

Stop plus at your stock limit and disable it there, the same way minus stops at 0.

API Reference

Button Group

Sets aria-label="Quantity" and aria-live="polite". The rest is on the Button Group page.

Button

Sets aria-label="Decrease quantity", disabled={quantity1 === 0}, onClick={decrement1}, size="icon-sm", variant="outline" and aria-label="Increase quantity". The rest is on the Button page.