NumberInput

NumberInput is a <input type=text> under the hood. This enables more freedom into what is displayed in the input. For example, we can display formatting commas.

The value we get is not consistently a number. For example, we get an empty string when the input is empty.

options

  • Forbid decimal numbers with allowDecimal. They are allowed by default.
  • Forbid negative numbers with allowNegative. They are allowed by default.
  • Clamp the value between min and max. Determine how the value should clamp with clampBehavior:
    • Forbid values outside the limits at all times with strict.
    • Clamp after input on blur. This is the default.
    • Never clamp (none)

As a text input, it supports a label, a description (secondary label) and a placeholder.

state

Work with the string and number type union:

const [value, setValue] = useState<string | number>("")
return <NumberInput value={value} onChange={setValue} />

Work with a number only. In this case, we only update state if the value is a number. When the NumberInput is empty, the state may have a ghost value. We clear the ghost value on blur if the field is empty.

const [value, setValue] = useState<number>(0)

return (
    <NumberInput
        value={value}
        onChange={(value) => {
            if (typeof value === "number") setValue(value)
        }}
        onFocus={(input) => {
            /* clear field to prepare for input if value was 0 */
            if (input.target.value === "0") {
                input.target.value = ""
            }
        }}
        onBlur={(input) => {
            /* reset field to 0 if empty on leaving the field */
            if (input.target.value === "") {
                onChange(0)
            }
        }}
    />
)
earlymorning logo

© Antoine Weber 2026 - All rights reserved

NumberInput

NumberInput is a <input type=text> under the hood. This enables more freedom into what is displayed in the input. For example, we can display formatting commas.

The value we get is not consistently a number. For example, we get an empty string when the input is empty.

options

  • Forbid decimal numbers with allowDecimal. They are allowed by default.
  • Forbid negative numbers with allowNegative. They are allowed by default.
  • Clamp the value between min and max. Determine how the value should clamp with clampBehavior:
    • Forbid values outside the limits at all times with strict.
    • Clamp after input on blur. This is the default.
    • Never clamp (none)

As a text input, it supports a label, a description (secondary label) and a placeholder.

state

Work with the string and number type union:

const [value, setValue] = useState<string | number>("")
return <NumberInput value={value} onChange={setValue} />

Work with a number only. In this case, we only update state if the value is a number. When the NumberInput is empty, the state may have a ghost value. We clear the ghost value on blur if the field is empty.

const [value, setValue] = useState<number>(0)

return (
    <NumberInput
        value={value}
        onChange={(value) => {
            if (typeof value === "number") setValue(value)
        }}
        onFocus={(input) => {
            /* clear field to prepare for input if value was 0 */
            if (input.target.value === "0") {
                input.target.value = ""
            }
        }}
        onBlur={(input) => {
            /* reset field to 0 if empty on leaving the field */
            if (input.target.value === "") {
                onChange(0)
            }
        }}
    />
)