# Stepper

Number input as minus, value and plus, with press-and-hold repeat and screen-reader adjust actions.

[Documentation](https://eoria.adamtrip.pt/components/stepper/)

[Registry source](https://eoria.adamtrip.pt/r/stepper.json)

npm dependencies: @eoria/core.

Registry dependencies: text.

```sh
npx @eoria/cli add stepper
```

## Usage

```tsx
import { useState } from 'react'
import { Stepper } from '@/components/ui/stepper'

export function Quantity() {
  const [quantity, setQuantity] = useState(1)
  return (
    <Stepper
      value={quantity}
      onValueChange={setQuantity}
      min={1}
      max={10}
      accessibilityLabel="Quantity"
    />
  )
}

<Stepper size="sm" defaultValue={0.5} min={0} max={5} step={0.5} formatValue={(n) => `${n} kg`} />
```

## Props

| Prop            | Values                                                                                         | Default    |
| --------------- | ---------------------------------------------------------------------------------------------- | ---------- |
| `value`         | number; controlled                                                                             |            |
| `defaultValue`  | number                                                                                         | `min`      |
| `min`, `max`    | number                                                                                         | `0`, `100` |
| `step`          | amount one press moves                                                                         | `1`        |
| `onValueChange` | `(value: number) => void`                                                                      |            |
| `formatValue`   | `(value: number) => string`, shown and announced                                               | `String`   |
| `size`          | `sm`, `md`, the heights of `theme.control`                                                     | `md`       |
| `disabled`      | boolean                                                                                        | `false`    |
| `styles`        | override `root`, `rootDisabled`, `button`, `buttonPressed`, `buttonDisabled`, `glyph`, `value` |            |

## Notes

A press moves the value by one `step`. Holding a button for 400 ms starts a repeat at 160 ms that shortens by 15% per tick down to 40 ms. It stops on release and at a bound. A button at its bound dims and stops taking presses.

The value is set in tabular figures with a minimum width, so the buttons hold still while the digits change. Steps such as 0.1 are rounded to the decimals of `step` and `min`, so 0.1 plus 0.2 shows 0.3.

For screen readers the whole control is one `adjustable` element. It reports `formatValue(value)` as its value and answers the increment and decrement actions by one `step`. The two buttons are for touch only. Give the Stepper an `accessibilityLabel`. The defaults of 0 to 100 follow UIStepper.

The minus and plus are drawn with bars from the `glyph` slot, so the file has no icon dependency. Buttons under 44pt get `hitSlop` upwards, downwards and outwards.

## Source

[`registry/ui/stepper.tsx`](https://github.com/adamtrip-solutions/eoria/blob/main/registry/ui/stepper.tsx)
