---
title: "NumberField"
description: "A numeric field with steppers, limits and step size. The input accepts a numeric keypad and the buttons carry aria-label."
kind: component
id: C-014
registry: "number-field"
docs: "https://koten.codehive.com.co/components/number-field"
markdown: "https://koten.codehive.com.co/md/components/number-field.md"
install: "npx shadcn@latest add https://koten.codehive.com.co/r/number-field.json"
language: en
---

# NumberField · 数値

> Component C-014 in the Koten UI catalog.

A numeric field with steppers, limits and step size. The input accepts a numeric keypad and the buttons carry aria-label.

> Japanese labels in this page are documentation metadata. Keep the consumer UI in the product's language and do not add Japanese decoration unless the user asks (R-031).

## Install

Install `koten-theme` first when the project does not have Koten tokens yet. Use the runner of your project.

```bash
# Node
npx shadcn@latest add https://koten.codehive.com.co/r/number-field.json

# Bun
bunx shadcn@latest add https://koten.codehive.com.co/r/number-field.json
```

## Files

- `@/components/ui/number-field.tsx`
- `@/lib/koten/cn.ts`
- `@/lib/koten/format.ts`
- `@/lib/koten/intl.ts`
- `@/lib/koten/labels.ts`
- `@/lib/koten/provider.tsx`

## Reference

- Upstream primitive: https://base-ui.com/react/components/number-field

## Examples

### Limits and step

min and max disable the steppers at the edges; step defines the increment.

```tsx
<NumberField
  label="Units"
  defaultValue={1}
  min={1}
  max={99}
  decrementLabel="Decrease by one"
  incrementLabel="Increase by one"
/>
<NumberField
  label="Locked quantity"
  defaultValue={12}
  disabled
  decrementLabel="Decrease by one"
  incrementLabel="Increase by one"
/>
```

### Controlled value

onValueChange returns a number or null, and the value can feed a calculation.

```tsx
const [quantity, setQuantity] = useState<number | null>(2);
const total = (quantity ?? 0) * 1200;

<NumberField
  label="Units"
  value={quantity ?? undefined}
  onValueChange={setQuantity}
  min={1}
  max={99}
  step={1}
  decrementLabel="Decrease by one"
  incrementLabel="Increase by one"
/>
<p className="text-2xs text-muted">
  Total:{" "}
  <span className="font-semibold tabular-nums text-ink">
    {formatCurrency(total)}
  </span>
</p>
```

### Use inside a form

The field starts empty, declares limits and step, and the error states the accepted range before adding units.

```tsx
<form
  className="grid w-full max-w-sm gap-[var(--koten-gap)]"
  onSubmit={(event) => event.preventDefault()}
>
  <div className="grid gap-1">
    <NumberField
      label="Units per pack"
      min={1}
      max={48}
      step={6}
      decrementLabel="Decrease by six"
      incrementLabel="Increase by six"
    />
    <p className="text-2xs leading-relaxed text-faint">
      Packs ship in multiples of six units.
    </p>
    <p role="alert" className="text-2xs leading-relaxed text-danger">
      Enter a quantity between 1 and 48.
    </p>
  </div>
  <div className="flex justify-end">
    <Button type="submit" variant="primary">Add to order</Button>
  </div>
</form>
```

## Props

| Prop | Type | Default | Notes |
| --- | --- | --- | --- |
| `label` | `string` | `—` | Visible label linked to the input through htmlFor/id; required. |
| `value / defaultValue` | `number` | `—` | Controlled or uncontrolled. |
| `min / max` | `number` | `—` | The steppers disable when a limit is reached. |
| `step` | `number` | `1` | Increment used by the steppers and the arrow keys. |
| `onValueChange` | `(value: number \| null) => void` | `—` | Returns the number, or null when the field is empty. |
| `decrementLabel / incrementLabel` | `string` | `—` | Required aria-label for the icon-only buttons. |
| `disabled / name` | `boolean / string` | `false / —` | name submits the value with the form; disabled blocks the whole group. |

## Accessibility

- The input declares a numeric inputmode, and the steppers carry decrementLabel and incrementLabel as aria-label.
- At min or max the buttons disable, so the limit is perceivable without reading the value.
- The value can be typed with the keyboard; the steppers are a shortcut, not the only way.

## Sources

- Catalog page: https://koten.codehive.com.co/components/number-field
- Markdown: https://koten.codehive.com.co/md/components/number-field.md
- Repository: https://github.com/codehive-colombia/koten
