PixelNumberInput

Numeric input with spin controls, clamp behaviors, precision, prefix/suffix, and thousands-separator formatting.

  • Spinbutton with ArrowUp/ArrowDown step bumps and clickable increment/decrement controls
  • Configurable clamp behavior (strict, on-blur, or none) with min/max bounds
  • Precision rounding avoids floating-point artifacts (e.g. 0.1 + 0.2)
  • Optional prefix, suffix, and thousands-separator with parse-aware display
  • Surface/tone aware; controlled — value + onChange (React), v-model (Vue), [(value)] or forms (Angular) — or uncontrolled with defaultValue
Status
stable
Category
forms
Since
v1.8.0

API

import { PixelNumberInput } from '@pxlkit/ui-kit';
PropTypeDefaultDescription
valuenumber—Value; leave unset for an uncontrolled field.
defaultValuenumber—Initial value while uncontrolled.
onChange(next: number) => void—Called with the new number, after each step, edit that reads as a number, or settle on blur.
minnumber—Lowest value.
maxnumber—Highest value.
stepnumber1Amount each step adds or removes.
precisionnumber—Decimals shown, and the value is rounded to.
clampBehavior'strict' | 'blur' | 'none''blur'When a value outside min / max is pulled back: while typing, on blur, or never.
prefixstring—Text inside the field on the left ($).
suffixstring—Text inside the field on the right (USD).
thousandsSeparatorstring—Groups the integer digits (, shows 1,500,000).
allowNegativebooleantrueAccepts negative numbers.
hideControlsbooleanfalseHides the stepper buttons.
size'sm' | 'md' | 'lg''md'Field height.
surface'pixel' | 'linear'—Surface override; defaults to the nearest provider.
tone'green' | 'cyan' | 'gold' | 'red' | 'purple' | 'pink' | 'neutral''neutral'Tone of the focus ring.
labelstring—Label rendered above the field.
hintstring—Helper text below the field; hidden while error is set.
errorstring—Error message below the field; marks the input invalid.

Also takes the native attributes and event handlers of <input> (InputHTMLAttributes<HTMLInputElement>), except type.

ref points to <input>.

Accessibility

WCAG target: 2.1 AA

  • spinbutton

Renders role="spinbutton" with aria-valuemin/aria-valuemax/aria-valuenow reflecting the current numeric state. Error state sets aria-invalid.

Keyboard

KeyActionWhen
ArrowUpIncrement value by step—
ArrowDownDecrement value by step—

Usage

import { useState } from 'react';
import { PixelNumberInput } from '@pxlkit/ui-kit';

export function Default() {
  const [value, setValue] = useState<number>(5);
  return (
    <PixelNumberInput
      label="Quantity"
      value={value}
      onChange={setValue}
      min={0}
      max={100}
    />
  );
}

Examples

Default

import { useState } from 'react';
import { PixelNumberInput } from '@pxlkit/ui-kit';

export function Default() {
  const [value, setValue] = useState<number>(5);
  return (
    <PixelNumberInput
      label="Quantity"
      value={value}
      onChange={setValue}
      min={0}
      max={100}
    />
  );
}

With Prefix & Suffix

import { useState } from 'react';
import { PixelNumberInput } from '@pxlkit/ui-kit';

export function WithPrefixSuffix() {
  const [value, setValue] = useState<number>(19.99);
  return (
    <PixelNumberInput
      label="Price"
      value={value}
      onChange={setValue}
      prefix="$"
      suffix="USD"
      precision={2}
      step={0.01}
      min={0}
    />
  );
}

Thousands Separator

import { useState } from 'react';
import { PixelNumberInput } from '@pxlkit/ui-kit';

export function ThousandsSeparator() {
  const [value, setValue] = useState<number>(1500000);
  return (
    <PixelNumberInput
      label="Population"
      value={value}
      onChange={setValue}
      thousandsSeparator=","
      min={0}
    />
  );
}

Hide Controls

import { useState } from 'react';
import { PixelNumberInput } from '@pxlkit/ui-kit';

export function HideControls() {
  const [value, setValue] = useState<number>(42);
  return (
    <PixelNumberInput
      label="Age"
      value={value}
      onChange={setValue}
      hideControls
      min={0}
      max={120}
    />
  );
}

With Error

import { useState } from 'react';
import { PixelNumberInput } from '@pxlkit/ui-kit';

export function WithError() {
  const [value, setValue] = useState<number>(150);
  return (
    <PixelNumberInput
      label="Score"
      value={value}
      onChange={setValue}
      min={0}
      max={100}
      error="Score must be between 0 and 100"
      tone="red"
    />
  );
}

Related