# Number stepper (goodtabs UI)

A number field with minus and plus buttons inside one border, clamped to min and max.

## Install

```bash
npx shadcn@latest add https://ui.goodtabs.co/r/number-stepper.json
```

Or, with the @goodtabs namespace configured in components.json: `npx shadcn@latest add @goodtabs/number-stepper`

## Usage

```tsx
import { NumberStepper } from "@/components/ui/number-stepper"

<NumberStepper label="Quantity" defaultValue={1} min={1} max={10} onValueChange={setQty} />
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| value | `number` |  | Controlled value. Leave out for an uncontrolled field. |
| defaultValue | `number` | `0` | Starting value for the uncontrolled form. |
| onValueChange | `(value: number) => void` |  | Fires with the new number after a step, a typed value commits or a clamp. |
| min | `number` |  | Lowest value. The minus button disables here. |
| max | `number` |  | Highest value. The plus button disables here. |
| step | `number` | `1` | Amount each step adds or removes. |
| label | `string` |  | Accessible name for the field, for example "Quantity". |
| size | `"sm" | "default"` | `"default"` | Control height, 28px or 32px. |

## When to use

- Quantities, counts, seats, hours: small numbers people nudge more than they type
- Carts, order lines and table cells, in the sm size
- Settings that have a clear floor and ceiling

## When not to use

- Large or precise numbers such as prices or ids, where typing is the whole job and a plain Input is better
- Picking from a range by feel: use a slider
- Values with units that change, like durations across hours and minutes

## Notes for agents

- It takes a function (onValueChange), so a demo or page that passes one must be a client component
- Always pass label; it becomes the aria-label on the input, there is no visible label of its own
- Typed values commit on blur or Enter and clamp to min and max; ArrowUp and ArrowDown step straight away
- Decimals follow step, so step={0.5} keeps one decimal and avoids float drift; the buttons are skipped by Tab since the arrows do the same job

Docs: https://ui.goodtabs.co/components/number-stepper