NumberInput

Capture number input from user
Import

Usage

Radius
xs
sm
md
lg
xl
Size
xs
sm
md
lg
xl
import { NumberInput } from '@mantine/core';
function Demo() {
return (
<NumberInput
defaultValue={18}
placeholder="Your age"
label="Your age"
withAsterisk
/>
);
}

Controlled

import { useState } from 'react';
import { NumberInput } from '@mantine/core';
function Demo() {
const [value, setValue] = useState(0);
return <NumberInput value={value} onChange={(val) => setValue(val)} />;
}

Clamp on blur

Component has internal state to manage user input, when blur event is triggered internal value is clamped with given min and max values and onChange handler is called with result.

For example, if you put 123 or -20 in age input in next example, values will be clamped on blur: 123 -> 120, -20 -> 0. If you want to disable this behavior set noClampOnBlur prop:

<NumberInput noClampOnBlur />

Parser and formatter

With parser and formatter props you can customize how value is displayed in the input:

import { NumberInput } from '@mantine/core';
function Demo() {
return (
<NumberInput
label="Price"
defaultValue={1000}
parser={(value) => value.replace(/\$\s?|(,*)/g, '')}
formatter={(value) =>
!Number.isNaN(parseFloat(value))
? `$ ${value}`.replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ',')
: '$ '
}
/>
);
}

Min, max and step

Min and max values define upper and lower value which may be entered. When user clicks controls or presses up/down arrows, value is incremented/decremented by step:

From 0 to 120, step is 1
From 0 to Infinity, step is 5
import { NumberInput } from '@mantine/core';
function Demo() {
return (
<>
<NumberInput
label="Your age"
description="From 0 to 120, step is 1"
placeholder="Your age"
max={120}
min={0}
/>
<NumberInput
mt="md"
label="Your weight in kg"
description="From 0 to Infinity, step is 5"
defaultValue={80}
step={5}
min={0}
/>
</>
);
}

Increment/decrement on hold

Set stepHoldDelay and stepHoldInterval props to define behavior when increment/decrement controls are clicked and hold, this will also overwrite default up and down arrows behavior:

Step the value when clicking and holding the arrows
Step value will increase incrementally when control is hold
import { NumberInput } from '@mantine/core';
function Demo() {
return (
<>
<NumberInput
style={{ marginTop: 15 }}
label="Step on hold"
description="Step the value when clicking and holding the arrows"
stepHoldDelay={500}
stepHoldInterval={100}
/>
<NumberInput
label="Step the value with interval function"
description="Step value will increase incrementally when control is hold"
stepHoldDelay={500}
stepHoldInterval={(t) => Math.max(1000 / t ** 2, 25)}
/>
</>
);
}

Decimal steps

To use decimal steps set following props:

  • step – decimal number, e.g. 0.05
  • precision – amount of significant digits
import { NumberInput } from '@mantine/core';
function Demo() {
return (
<NumberInput
label="Number input with decimal steps"
defaultValue={0.05}
precision={2}
min={-1}
step={0.05}
max={1}
/>
);
}

Decimal separator

To change decimal separator set decimalSeparator prop:

import { NumberInput } from '@mantine/core';
function Demo() {
return (
<NumberInput
decimalSeparator=","
label="Number input with a custom decimal separator"
defaultValue={0.5}
precision={2}
step={0.5}
/>
);
}

Remove controls

Controls are not rendered in these cases:

  • hideControls prop is set to true
  • Input is disabled
  • variant prop is set to unstyled
import { NumberInput } from '@mantine/core';
function Demo() {
return (
<>
<NumberInput label="By default controls are visible" />
<NumberInput
hideControls
label="Disable them with hideControls prop"
/>
<NumberInput
label="Disabled"
disabled
label="Controls also not rendered when input is disabled"
/>
</>
);
}

Custom increment/decrement controls

NumberInput exposes increment/decrement functions with handlersRef prop. You can use it to create custom controls:

import { useState, useRef } from 'react';
import { NumberInput, Group, ActionIcon, NumberInputHandlers } from '@mantine/core';
function Demo() {
const [value, setValue] = useState(0);
const handlers = useRef<NumberInputHandlers>();
return (
<Group spacing={5}>
<ActionIcon size={42} variant="default" onClick={() => handlers.current.decrement()}>
</ActionIcon>
<NumberInput
hideControls
value={value}
onChange={(val) => setValue(val)}
handlersRef={handlers}
max={10}
min={0}
step={2}
styles={{ input: { width: 54, textAlign: 'center' } }}
/>
<ActionIcon size={42} variant="default" onClick={() => handlers.current.increment()}>
+
</ActionIcon>
</Group>
);
}

Invalid state and error

You must be at least 21
// Error as boolean – red border color
<NumberInput error />
// Error as React node – red border color and message below input
<NumberInput error="You must be at least 21" />

Disabled state

Controls to increment/decrement value are not displayed when input is disabled:

import { NumberInput } from '@mantine/core';
function Demo() {
return <NumberInput disabled />;
}

With icon

import { NumberInput } from '@mantine/core';
import { IconMedal } from '@tabler/icons';
function Demo() {
return (
<NumberInput
label="Age when you graduated"
placeholder="Age when you graduated"
defaultValue={22}
min={0}
max={120}
icon={<IconMedal size={18} />}
/>
);
}

Get input ref

import { useRef } from 'react';
import { NumberInput } from '@mantine/core';
function Demo() {
const ref = useRef<HTMLInputElement>(null);
return <NumberInput ref={ref} />;
}

Accessibility

NumberInput renders regular input with type="text". Increment/decrement controls have aria-hidden attribute and cannot be focused – users with keyboard can increment/decrement value by step with up/down arrows.

Provide aria-label in case you use component without label for screen reader support:

<NumberInput /> // -> not ok, input is not labeled
<NumberInput label="Your age" /> // -> ok, input and label is connected
<NumberInput aria-label="Your age" /> // -> ok, label is not visible but will be announced by screen reader

NumberInput component props

NameTypeDescription
decimalSeparator
string
The decimal separator
defaultValue
number
Default value for uncontrolled variant only
description
ReactNode
Input description, displayed after label
descriptionProps
Record<string, any>
Props spread to description element
disabled
boolean
Disabled input state
error
ReactNode
Displays error message after input
errorProps
Record<string, any>
Props spread to error element
formatter
Formatter
Formats the number into the input
handlersRef
ForwardedRef<NumberInputHandlers>
Get increment/decrement handlers
hideControls
boolean
Removes increment/decrement controls
icon
ReactNode
Adds icon on the left side of input
iconWidth
Width<string | number>
Width of icon section in px
inputContainer
(children: ReactNode) => ReactNode
Input container component, defaults to React.Fragment
inputWrapperOrder
("input" | "label" | "error" | "description")[]
Controls order of the Input.Wrapper elements
label
ReactNode
Input label, displayed before input
labelProps
Record<string, any>
Props spread to label element
max
number
Maximum possible value
min
number
Minimal possible value
noClampOnBlur
boolean
Prevent value clamp on blur
onChange
(value: number) => void
onChange input handler for controlled variant, note that input event is not exposed. It will return undefined if the input is empty, otherwise it'll return a number
parser
Parser
Parses the value from formatter, should be used with formatter at the same time
precision
number
Amount of digits after the decimal point
radius
number | "xs" | "sm" | "md" | "lg" | "xl"
Input border-radius from theme or number to set border-radius in px
removeTrailingZeros
boolean
Only works if a precision is given, removes the trailing zeros, false by default
required
boolean
Sets required on input element
rightSection
ReactNode
Right section of input, similar to icon but on the right
rightSectionProps
Record<string, any>
Props spread to rightSection div element
rightSectionWidth
Width<string | number>
Width of right section, is used to calculate input padding-right
size
"xs" | "sm" | "md" | "lg" | "xl"
Input size
startValue
number
First value if no initial value was set and increment/decrement is triggered using controls or up/down arrows
step
number
Number by which value will be incremented/decremented with controls and up/down arrows
stepHoldDelay
number
Initial delay in milliseconds before stepping the value.
stepHoldInterval
number | ((stepCount: number) => number)
Delay before stepping the value. Can be a number of milliseconds or a function that receives the current step count and returns the delay in milliseconds.
type
"number" | "text"
Input type, defaults to text
value
number
Input value for controlled variant
variant
"unstyled" | "default" | "filled"
Defines input appearance, defaults to default in light color scheme and filled in dark
withAsterisk
boolean
Determines whether required asterisk should be rendered, overrides required prop, does not add required attribute to the input
wrapperProps
Record<string, any>
Props passed to root element (InputWrapper component)

NumberInput component Styles API

NameStatic selectorDescription
wrapper.mantine-NumberInput-wrapperRoot Input element
invalid.mantine-NumberInput-invalidInvalid input modifier
disabled.mantine-NumberInput-disabledInvalid disabled modifier
icon.mantine-NumberInput-iconInput icon wrapper on the left side of the input, controlled by icon prop
withIcon.mantine-NumberInput-withIconInput element styles when used with icon, controlled by icon prop
input.mantine-NumberInput-inputMain input element
rightSection.mantine-NumberInput-rightSectionRight section with up and down controls
root.mantine-NumberInput-rootRoot element
label.mantine-NumberInput-labelLabel element styles, defined by label prop
error.mantine-NumberInput-errorError element styles, defined by error prop
description.mantine-NumberInput-descriptionDescription element styles, defined by description prop
required.mantine-NumberInput-requiredRequired asterisk element styles, defined by required prop
control.mantine-NumberInput-controlShared up and down controls styles
controlUp.mantine-NumberInput-controlUpUp control styles
controlDown.mantine-NumberInput-controlDownDown control styles