JGuang

NumberInput

NumberInput · Astryx

Preview
npm install @astryxdesign/core@0.7.1 @astryxdesign/theme-neutral@0.7.1 @stylexjs/stylex@0.19.0

NumberInput

A form input for numeric values with built-in validation, min/max constraints, and step controls. Use NumberInput for quantities, measurements, percentages, and similar inputs.

Installation

npm install @astryxdesign/core@0.7.1 @astryxdesign/theme-neutral@0.7.1 @stylexjs/stylex@0.19.0

Requires React 19+, base CSS and a Theme provider. See Setup.

Number Input

A form input for numeric values with built-in validation, min/max constraints, and step controls. Use NumberInput for quantities, measurements, percentages, and similar inputs.

PropTypeDefaultDescription
label *stringLabel text for the input (always rendered for accessibility).
value *number | null | undefinedCurrent value of the input.
onChange *(value: number) => voidCallback fired when a valid text edit commits on blur or Enter, or when a step or clear control changes the value.
size'sm' | 'md' | 'lg''md'Size variant.
isLabelHiddenbooleanVisually hide the label (still accessible to screen readers).
descriptionstringDescription text displayed between the label and input.
isOptionalbooleanWhether the field is optional (mutually exclusive with isRequired).
onKeyDown(e: KeyboardEvent<HTMLInputElement>) => voidCallback fired on keydown events on the input.
isRequiredbooleanWhether the field is required (mutually exclusive with isOptional).
isDisabledbooleanWhether the input is disabled.
isReadOnlybooleanfalseMakes the input read-only: the value is shown at full opacity and still submits with the form, but cannot be edited. Unlike isDisabled, a read-only input is not dimmed and stays in the tab order. Stepping is off in every form while read-only: arrow keys, the wheel, and the number steppers. isDisabled takes precedence when both are set.
disabledMessagestringExplains why the input is disabled. With isDisabled, shows a tooltip on hover/keyboard focus and keeps the input focusable via aria-disabled (the field becomes read-only). Use this instead of wrapping a disabled NumberInput in Tooltip.
placeholderstringPlaceholder text.
labelTooltipstringTooltip text to display in an info icon at the end of the label.
startIconIconTypeIcon to display at the start of the input. See astryx docs icons for valid semantic names.
labelIconIconTypeIcon to display before the label text. See astryx docs icons for valid semantic names.
status{type: 'error' | 'warning' | 'success', message?: string}Validation status with optional message.
statusVariant'attached' | 'detached' | 'tooltip''attached'How the status message is placed relative to the input. attached overlaps directly below the input (bordered treatment); detached floats below as a separate element with spacing; tooltip hides the message box and surfaces it in a tooltip on the status icon.
minnumber | nullMinimum value allowed. A smaller entry commits at this value on blur or Enter.
maxnumber | nullMaximum value allowed. A larger entry commits at this value on blur or Enter.
stepnumber | null1Step increment for the input.
formatValue(value: number) => stringFormats the committed value while the input is not focused. The raw numeric value is shown on focus for editing and the formatted value is exposed through aria-valuetext.
isWheelEnabledbooleantrueWhether scrolling the wheel over the focused input steps the value. Disable this when page scrolling should always take priority.
hasNumberSteppersbooleanfalseShows increment and decrement buttons at the end of the input.
unitsstring | nullUnits text to display at the end of the input (e.g., "%" or "GB").
isIntegerOnlybooleanOnly allow integer values (no floating point).
hasClearbooleanfalseShows a clear (×) button when the input has a value. When true, the onChange callback also accepts null to signal the user cleared the input.
htmlNamestringHTML name attribute for form submissions.
autoCompletestringHTML autocomplete attribute.
widthSizeValueWidth of the field (number = pixels, string used as-is, e.g. "100%"). Sizes the whole field (label, control, and status) so they stay aligned.
hasAutoFocusbooleanWhether to focus the input on mount.
onFocus(e: FocusEvent<HTMLInputElement>) => voidCallback fired when the input receives focus.
onBlur(e: FocusEvent<HTMLInputElement>) => voidCallback fired when the input loses focus.
onEnter() => voidCallback fired when the user presses the Enter key.
containerXstyleStyleXStylesStyleX styles for the field container (label, control, and status together). No effect inside InputGroup (style the InputGroup instead) or in a horizontal-labels FormLayout. Root xstyle, className, and style are not accepted.
containerClassNamestringClass name for the field container. Same targeting as containerXstyle.
containerStyleCSSPropertiesInline styles for the field container. Same targeting as containerXstyle.
controlXstyleStyleXStylesStyleX styles for the visual control box: the element that paints the border and background and holds icons and end controls. Never the native input.
controlClassNamestringClass name for the visual control box.
controlStyleCSSPropertiesInline styles for the visual control box.

Usage guidance

  • Let people paste formatted numbers: a pasted 1,234,234,234 is read under the field's locale and commits as 1234234234 on blur. Typing is never intercepted.
  • Set min, max, and step to guide users toward valid values.
  • Show units (e.g. "%" or "GB") so users know what the number represents.
  • Set isWheelEnabled={false} when the input appears in a scrolling surface where wheel gestures should always scroll the page.
  • Avoid: Use NumberInput for free-form text that happens to contain numbers; use TextInput instead.
  • Avoid: Set both isOptional and isRequired on the same field.
  • Avoid: Wrap a disabled NumberInput in Tooltip to explain why it's disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead.

Theming API

{
  "targets": [
    {
      "className": "astryx-number-input",
      "visualProps": [
        "size",
        "status"
      ],
      "states": [
        "disabled",
        "readonly"
      ]
    }
  ],
  "derived": [
    {
      "property": "padding",
      "expand": "container"
    },
    {
      "property": "borderRadius",
      "vars": [
        "--_field-radius"
      ]
    }
  ]
}

Anatomy

  • Label: The label for the number input.
  • Description: Additional description text below the label.
  • Icon: An optional icon within the input.
  • Placeholder: Placeholder text shown when the input is empty.
  • Number steppers: Optional buttons that increment or decrement by the configured step.

Examples

  • Number Input: A number input for quantity entry.
  • NumberInput — Clearable: Number input with a clear button, unit suffix, and min/max constraint
  • NumberInput — Range Constrained: Number input with min/max boundaries and a helper description
  • NumberInput — Status Variants: Number inputs showing error, warning, and success validation states
  • NumberInput — With Units: Number input with a percentage unit suffix and valid range