designComponents

Search the design system…

Search the design system…

primitives

NumberField

Numeric input with a styled stepper — replaces the browser's native number spinner (which can't be themed). Arrows nudge by `step`, clamped to min/max; the value stays type-able.

Install

Pull this component (and its dependencies) straight into your app via the shadcn CLI:

npx shadcn@latest add https://design.oapps.io/r/number-field.json

Or import from the workspace package:

import { NumberField } from "@8maverik8/design";

Examples

Stepper field — vertical & horizontal

Arrows add/subtract `step` and clamp to min/max; you can also type. Default is the vertical up/down stepper; pass `orientation="horizontal"` for the `− [value] +` layout (shown below).

const [value, setValue] = useState("12");

<NumberField
  className="w-40"
  min={1}
  max={120}
  step={1}
  value={value}
  onChange={setValue}
  aria-label="Months"
/>

{/* horizontal − [value] + stepper */}
<NumberField
  orientation="horizontal"
  className="w-44"
  min={0}
  placeholder="Not set"
  value={reps}
  onChange={setReps}
  aria-label="Reps"
/>

Guidelines

  • Use for bounded numeric fields — counts, months, percentages, quantities.
  • Use a raw `<input type="number">` — its native spinner is unthemeable and reads as off-brand.NumberField composes the DS Input (so it inherits the skin) and paints its own stepper. Hide the native spinner globally so stray number inputs match.
  • Drive it controlled — `value` is a string so the field can be empty or mid-edit; coerce with `Number(value)` on save.
  • Forget `min`/`max` — the steppers clamp to them, which is the main reason to use it over a plain input.
  • Use `orientation="horizontal"` for a `− [value] +` side-button stepper (value centred, each button with its own hover/press background) when it reads better in dense config rows.