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.jsonOr 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.