NumberInput

Capture number input from user
Import

Usage

NumberInput is based on TextInput and supports the same props, except rightSection. See full information about shared inputs props in inputs guide.

Radius
<NumberInput
defaultValue={18}
placeholder="Your age"
label="Your age"
required
/>

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 />

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
<NumberInput
label="Your age"
description="From 0 to 120, step is 1"
placeholder="Your age"
max={120}
min={0}
/>
<NumberInput
style={{ marginTop: 15 }}
label="Your weight in kg"
description="From 0 to Infinity, step is 5"
defaultValue={80}
step={5}
min={0}
/>

Remove controls

Controls are not rendered in these cases:

  • hideControls prop is set to true
  • Input is disabled
  • variant prop is set to unstyled
<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 React, { useState, useRef } from 'react';
import { NumberInput, Group, ActionIcon, NumberInputHandlers } from '@mantine/core';
function HandlersWrapper() {
const [value, setValue] = useState(0);
const handlers = useRef<NumberInputHandlers>();
return (
<Group spacing={5}>
<ActionIcon size={36} variant="outline" onClick={() => handlers.current.decrement()}>
</ActionIcon>
<NumberInput
hideControls
value={value}
onChange={(val) => setValue(val)}
handlersRef={handlers}
max={10}
min={0}
step={2}
inputStyle={{ width: 54, textAlign: 'center' }}
/>
<ActionIcon size={36} variant="outline" onClick={() => handlers.current.increment()}>
+
</ActionIcon>
</Group>
);
}

Controlled

Unlike other Mantine inputs NumberInput does not expose input event in onChange handler, it provides value instead.

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

Get element ref

You can get input ref with elementRef prop:

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

Accessibility

NumberInput renders regular input with type="number". Increment/decrement controls have aria-hidden attribute and cannot be focused.

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

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