agentic-ui logoagentic-ui

Number Field

A numeric input with stepper buttons and a scrub area. Supports min/max clamping, step size, locale-aware formatting, and keyboard/scroll input.

Variants

import { NumberField } from "@brijbyte/agentic-ui/number-field";

import "@brijbyte/agentic-ui/number-field.css";

export default function BasicDemo() {
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: "var(--space-4)" }}>
      <NumberField label="Quantity" defaultValue={1} min={0} max={100} />
      <NumberField label="Timeout (ms)" defaultValue={3000} step={500} min={0} />
      <NumberField label="Price" defaultValue={9.99} step={0.01} format={{ style: "currency", currency: "USD" }} />
    </div>
  );
}

Composed: base-ui Root + styled parts

import { useId } from "react";
import { NumberField } from "@base-ui/react/number-field";
import {
  NumberFieldGroup,
  NumberFieldInput,
  NumberFieldDecrement,
  NumberFieldIncrement,
  NumberFieldScrubArea,
  NumberFieldScrubAreaCursor,
} from "@brijbyte/agentic-ui/number-field";

import "@brijbyte/agentic-ui/number-field.css";

function ScrubCursorIcon() {
  return (
    <svg width="24" height="12" viewBox="0 0 24 14" fill="currentColor" stroke="white" strokeWidth="0.5" aria-hidden>
      <path d="M19.5 5.5L6.49737 5.51844V2L1 6.9999L6.5 12L6.49737 8.5L19.5 8.5V12L25 6.9999L19.5 2V5.5Z" />
    </svg>
  );
}

export default function ComposedDemo() {
  const id = useId();

  return (
    <NumberField.Root
      id={id}
      defaultValue={42}
      min={0}
      max={999}
      style={{ display: "flex", flexDirection: "column", gap: "var(--space-1)" }}
    >
      <NumberFieldScrubArea>
        <label
          htmlFor={id}
          style={{
            cursor: "ew-resize",
            fontFamily: "var(--font-mono)",
            fontSize: "var(--font-size-xs)",
            fontWeight: "var(--font-weight-medium)",
            color: "var(--color-secondary)",
            textTransform: "uppercase",
            letterSpacing: "var(--letter-spacing-wide)",
          }}
        >
          Custom label
        </label>
        <NumberFieldScrubAreaCursor>
          <ScrubCursorIcon />
        </NumberFieldScrubAreaCursor>
      </NumberFieldScrubArea>

      <NumberFieldGroup>
        <NumberFieldDecrement></NumberFieldDecrement>
        <NumberFieldInput />
        <NumberFieldIncrement>+</NumberFieldIncrement>
      </NumberFieldGroup>
    </NumberField.Root>
  );
}

API Reference

NumberField

base-ui docs ↗

A numeric input with stepper buttons and a scrub area. Supports min/max
clamping, step size, locale-aware formatting, and keyboard/scroll input.

PropTypeDefault
labelReactNode

Visible label text. When present a scrub-area is also rendered.

defaultValuenumber

Initial value (uncontrolled).

valuenumber | null

Current value (controlled). null when the field is empty.

onValueChange((value: number | null) => void)

Called when the value changes.

minnumber

Minimum allowed value.

maxnumber

Maximum allowed value.

stepnumber1

Increment/decrement step size.

disabledboolean

Prevent interaction.

readOnlyboolean

Allow reading but not editing.

requiredboolean

Mark the field as required for form validation.

namestring

HTML name attribute for form submission.

formatNumberFormatOptions

Intl.NumberFormatOptions for display formatting.

allowWheelScrubboolean

Allow changing the value by scrolling the mouse wheel.

classNamestring

Styled Parts

base-ui docs ↗

Pre-styled wrappers around the corresponding base-ui parts. All base-ui props are forwarded.

CSS Class Names

Available as keys on the NumberFieldStyles object. Each key maps to a hashed CSS module class name at runtime.

decrementgroupincrementinputlabelrootscrub-areascrub-area-cursorstep-button