Skip to content
hightouchUI

Design system

97dff0e

Number input

Number input allows user to enter a number, with stepper buttons, min/max/step bounds, and locale-aware formatting. Note that the integer input is under TextInput as it uses a string value to handle bigints.

Example

Pair an input with a form field label wherever the layout allows, so the input is named for everyone, including screen reader users.

Usage

Formatting

Number input uses Intl.NumberFormat to format the input value. The default formatting style is decimal, but you can configure it via formatOptions prop.

Percentages

Number input supports percentage values. When style: "percent" formatting option is used, value is multiplied by 100 before it's displayed. When the user enters a value, the onChange callback will be triggered with the entered value divided by 100. The default step also automatically changes to 0.01, so that incrementing and decrementing occurs by 1%.

Minimum and maximum values

Number input can limit the entered value to a specific range via min and max props.

Placeholder text

Number input can show placeholder text before any value is entered.

Without a visible label

When the layout can't show a label, pass aria-label (or aria-labelledby, when the label text already renders elsewhere) so the input is still named for screen reader users. The two props are mutually exclusive, and the types enforce it: react-aria joins both into one name rather than preferring either, so passing both would announce the field twice over. Wrapping the input in a visually hidden <label> element is not a substitute: number input is a react-aria field, and it takes its name from these props rather than from the surrounding DOM, so a DOM-only label still logs a missing-label warning in development and loses out to whatever react-aria wires up itself. Inside a form field, aria-label replaces the visible label as the input's accessible name instead of adding to it. Only pass it there when the form field labels a group of controls rather than this input; when it labels the input, leave aria-label off so the accessible name matches the visible text.

Step values

Use step prop to customize the amount by which the value is incremented or decremented at a time.

Disabled

Input should be disabled, when input shouldn't be allowed to be interacted with.

Read only

Compared to a disabled input, read only input is usually used for values that user might want to copy to clipboard.

Invalid

Invalid input indicates that value isn't what the system expects.

Size

The size prop impacts font-size and height. Default is set to md.

To set the width, use the width prop instead.

Guidelines

When to use

  • When user enters an exact numeric value. Prefer it over a text input with type="number".

When not to use

  • If picking an imprecise value within a fixed range, use a slider instead.
  • If the value is an integer that can exceed JavaScript's safe number range, use a text input with type="integer" instead.

Content

  • Use sentence case for placeholder text.
  • End placeholder text with three dots.

Values

  • Code that uses number input should handle undefined gracefully and revert to an appropriate default value. undefined is returned as the value in the onChange callback when user clears out the number input.

Props

Inherits margin props.

NameDefaultDescription
autoFocusfalsebooleanWhether the input should be focused when mounted.
isDisabledfalsebooleanDetermines whether input is disabled and doesn't respond to any user interactions.
isReadOnlyfalsebooleanDetermines whether input can be interacted with, but value can't be changed.
isRequiredfalsebooleanIndicates that input is required to fill out.
isInvalidfalsebooleanIndicates that input value is invalid.
formatOptions{ style: "decimal" }Intl.NumberFormatOptionsFormatting options for the value displayed in the number field. This also affects what characters are allowed to be typed by the user.
min

—

numberThe smallest value allowed for the input.
max

—

numberThe largest value allowed for the input.
placeholder

—

stringThe text hint to show before any input is entered.
step

—

numberThe amount that the input value changes with each increment or decrement.
value

—

number | undefinedInput value.
width"xs""xs" | "sm" | "md" | "lg" | "auto" | "100%"Input width.
size"md""sm" | "md" | "lg"Input size.
onChange

—

(value: number | undefined) => voidThe callback fired when the value changes.
aria-label

—

stringLabel that describes the purpose of this input for screen readers. Use when the input has no visible label, i.e. it isn't wrapped in a FormField. Mutually exclusive with aria-labelledby: react-aria joins the two into one name ("<aria-label> <labelled-by text>") rather than preferring either.
aria-labelledby

—

stringID of the element that labels this input. Use when a visible label exists but can't be wired up through FormField. Mutually exclusive with aria-label.