Number Input
Used to enter a number, and increment or decrement the value using stepper buttons.
import { NumberInput } from "@chakra-ui/react"
const Demo = () => {
return (
<NumberInput.Root defaultValue="10" width="200px">
<NumberInput.Control />
<NumberInput.Input />
</NumberInput.Root>
)
}
Usage
import { NumberInput } from "@chakra-ui/react"<NumberInput.Root>
<NumberInput.Label />
<NumberInput.ValueText />
<NumberInput.Control>
<NumberInput.IncrementTrigger />
<NumberInput.DecrementTrigger />
</NumberInput.Control>
<NumberInput.Scrubber />
<NumberInput.Input />
</NumberInput.Root>Shortcuts
The NumberInput component provides a set of shortcuts for common use cases
NumberInputControl
This component renders the NumberInput.IncrementTrigger and
NumberInput.DecrementTrigger within it by default.
Writing this:
<NumberInput.Control />is shorthand for writing this if you don't need to customize the triggers:
<NumberInput.Control>
<NumberInput.IncrementTrigger />
<NumberInput.DecrementTrigger />
</NumberInput.Control>Examples
Sizes
Pass the size prop to the NumberInput.Root component to change the size of
the number input.
import { For, NumberInput, Stack } from "@chakra-ui/react"
const Demo = () => {
return (
<Stack gap="5" width="200px">
<For each={["xs", "sm", "md", "lg"]}>
{(size) => (
<NumberInput.Root size={size} key={size} defaultValue="10">
<NumberInput.Control />
<NumberInput.Input />
</NumberInput.Root>
)}
</For>
</Stack>
)
}
Formatting
Pass the formatOptions prop to the NumberInput.Root component to format the
number input value. The value of this maps to Intl.NumberFormatOptions and is
applied based on the current locale.
import { NumberInput, Stack } from "@chakra-ui/react"
const Demo = () => {
return (
<Stack gap="5" maxW="200px">
<NumberInput.Root
defaultValue="5"
step={0.01}
formatOptions={{
style: "percent",
}}
>
<NumberInput.Control />
<NumberInput.Input />
</NumberInput.Root>
<NumberInput.Root
defaultValue="45"
formatOptions={{
style: "currency",
currency: "EUR",
currencyDisplay: "code",
currencySign: "accounting",
}}
>
<NumberInput.Control />
<NumberInput.Input />
</NumberInput.Root>
<NumberInput.Root
defaultValue="4"
formatOptions={{
style: "unit",
unit: "inch",
unitDisplay: "long",
}}
>
<NumberInput.Control />
<NumberInput.Input />
</NumberInput.Root>
</Stack>
)
}
Min and Max
Pass the min and max props to the NumberInput.Root component to set the
minimum and maximum values of the number input.
If value entered is less than min or greater than max, the value will be
clamped to the nearest boundary on blur, or enter key press.
import { NumberInput } from "@chakra-ui/react"
const Demo = () => {
return (
<NumberInput.Root width="200px" defaultValue="10" min={5} max={50}>
<NumberInput.Control />
<NumberInput.Input />
</NumberInput.Root>
)
}
Step
Pass the step prop to the NumberInput.Root component to change the increment
or decrement interval of the number input.
import { NumberInput } from "@chakra-ui/react"
const Demo = () => {
return (
<NumberInput.Root maxW="200px" defaultValue="2" step={3}>
<NumberInput.Control />
<NumberInput.Input />
</NumberInput.Root>
)
}
Controlled
Pass the value and onValueChange props to the NumberInput.Root component
to control the value of the number input.
"use client"
import { NumberInput } from "@chakra-ui/react"
import { useState } from "react"
const Demo = () => {
const [value, setValue] = useState("10")
return (
<NumberInput.Root
maxW="200px"
value={value}
onValueChange={(e) => setValue(e.value)}
>
<NumberInput.Control />
<NumberInput.Input />
</NumberInput.Root>
)
}
Mobile Stepper
Here's an example of how to compose the number input as a mobile stepper.
import { HStack, IconButton, NumberInput } from "@chakra-ui/react"
import { LuMinus, LuPlus } from "react-icons/lu"
const Demo = () => {
return (
<NumberInput.Root defaultValue="3" unstyled spinOnPress={false}>
<HStack gap="2">
<NumberInput.DecrementTrigger asChild>
<IconButton variant="outline" size="sm">
<LuMinus />
</IconButton>
</NumberInput.DecrementTrigger>
<NumberInput.ValueText textAlign="center" fontSize="lg" minW="3ch" />
<NumberInput.IncrementTrigger asChild>
<IconButton variant="outline" size="sm">
<LuPlus />
</IconButton>
</NumberInput.IncrementTrigger>
</HStack>
</NumberInput.Root>
)
}
Mouse Wheel
Pass the allowMouseWheel prop to the NumberInput.Root component to enable or
disable the mouse wheel to change
import { NumberInput } from "@chakra-ui/react"
const Demo = () => {
return (
<NumberInput.Root defaultValue="10" width="200px" allowMouseWheel>
<NumberInput.Control />
<NumberInput.Input />
</NumberInput.Root>
)
}
Disabled
Pass the disabled prop to the NumberInput.Root component to disable the
number input.
import { NumberInput } from "@chakra-ui/react"
const Demo = () => {
return (
<NumberInput.Root defaultValue="10" width="200px" disabled>
<NumberInput.Control />
<NumberInput.Input />
</NumberInput.Root>
)
}
Invalid
Use the Field component and the invalid prop to indicate that the number
input is invalid.
import { Field, NumberInput } from "@chakra-ui/react"
const Demo = () => {
return (
<Field.Root invalid>
<Field.Label>Enter Number</Field.Label>
<NumberInput.Root defaultValue="10" width="200px">
<NumberInput.Control />
<NumberInput.Input />
</NumberInput.Root>
<Field.ErrorText>The entry is invalid</Field.ErrorText>
</Field.Root>
)
}
Helper Text
Compose the Field and Field.HelperText components to add helper text to the
number input.
import { Field, NumberInput } from "@chakra-ui/react"
const Demo = () => {
return (
<Field.Root>
<Field.Label>Enter Number</Field.Label>
<NumberInput.Root width="200px">
<NumberInput.Control />
<NumberInput.Input />
</NumberInput.Root>
<Field.HelperText>Enter a number between 1 and 10</Field.HelperText>
</Field.Root>
)
}
Element
Here's an example of how to compose the number input with the input group component to add an element on either the left or right.
import { InputGroup, NumberInput } from "@chakra-ui/react"
import { LuDollarSign } from "react-icons/lu"
const Demo = () => {
return (
<NumberInput.Root defaultValue="10" width="200px">
<NumberInput.Control />
<InputGroup startElement={<LuDollarSign />}>
<NumberInput.Input />
</InputGroup>
</NumberInput.Root>
)
}
Scrubber
Use the NumberInput.Scrubber component to make the number input supports
scrubber interactions.
import { InputGroup, NumberInput } from "@chakra-ui/react"
import { LuArrowRightLeft } from "react-icons/lu"
const Demo = () => {
return (
<NumberInput.Root defaultValue="10" width="200px">
<NumberInput.Control />
<InputGroup
startElementProps={{ pointerEvents: "auto" }}
startElement={
<NumberInput.Scrubber>
<LuArrowRightLeft />
</NumberInput.Scrubber>
}
>
<NumberInput.Input />
</InputGroup>
</NumberInput.Root>
)
}
Hook Form
Here is an example of how to use the NumberInput component with
react-hook-form.
"use client"
import { Button, Field, NumberInput } from "@chakra-ui/react"
import { standardSchemaResolver } from "@hookform/resolvers/standard-schema"
import { Controller, useForm } from "react-hook-form"
import { z } from "zod"
const formSchema = z.object({
number: z.string({ message: "Number is required" }),
})
type FormValues = z.infer<typeof formSchema>
const Demo = () => {
const {
control,
handleSubmit,
formState: { errors },
} = useForm<FormValues>({
resolver: standardSchemaResolver(formSchema),
})
const onSubmit = handleSubmit((data) => console.log(data))
return (
<form onSubmit={onSubmit}>
<Field.Root invalid={!!errors.number}>
<Field.Label>Number</Field.Label>
<Controller
name="number"
control={control}
render={({ field }) => (
<NumberInput.Root
disabled={field.disabled}
name={field.name}
value={field.value}
onValueChange={({ value }) => {
field.onChange(value)
}}
>
<NumberInput.Control />
<NumberInput.Input onBlur={field.onBlur} />
</NumberInput.Root>
)}
/>
<Field.ErrorText>{errors.number?.message}</Field.ErrorText>
</Field.Root>
<Button size="sm" type="submit" mt="4">
Submit
</Button>
</form>
)
}
Closed Component
Here's how to setup the Number Input for a closed component composition.
import { NumberInput as ChakraNumberInput } from "@chakra-ui/react"
import * as React from "react"
export interface NumberInputProps extends ChakraNumberInput.RootProps {}
export const NumberInputRoot = React.forwardRef<
HTMLDivElement,
NumberInputProps
>(function NumberInput(props, ref) {
const { children, ...rest } = props
return (
<ChakraNumberInput.Root ref={ref} variant="outline" {...rest}>
{children}
<ChakraNumberInput.Control>
<ChakraNumberInput.IncrementTrigger />
<ChakraNumberInput.DecrementTrigger />
</ChakraNumberInput.Control>
</ChakraNumberInput.Root>
)
})
export const NumberInputField = ChakraNumberInput.Input
export const NumberInputScrubber = ChakraNumberInput.Scrubber
export const NumberInputLabel = ChakraNumberInput.Label
If you want to automatically add the closed component to your project, run the command:
npx @chakra-ui/cli snippet add number-inputHere's how to use the it
<NumberInputRoot>
<NumberInputField />
</NumberInputRoot>Props
Root
| Prop | Default | Type |
|---|---|---|
allowOverflow | true | booleanWhether to allow the value overflow the min/max range |
clampValueOnBlur | true | booleanWhether to clamp the value when the input loses focus (blur) |
focusInputOnChange | true | booleanWhether to focus input when the value changes |
inputMode | '\'decimal\'' | InputModeHints at the type of data that might be entered by the user. It also determines the type of keyboard shown to the user on mobile devices |
locale | '\'en-US\'' | stringThe current locale. Based on the BCP 47 definition. |
max | 'Number.MAX_SAFE_INTEGER' | numberThe maximum value of the number input |
min | 'Number.MIN_SAFE_INTEGER' | numberThe minimum value of the number input |
pattern | '\'-?[0-9]*(.[0-9]+)?\'' | stringThe pattern used to check the <input> element's value against |
spinOnPress | true | booleanWhether to spin the value when the increment/decrement button is pressed |
step | '1' | numberThe amount to increment or decrement the value by |
colorPalette | 'gray' | 'gray' | 'red' | 'orange' | 'yellow' | 'green' | 'teal' | 'blue' | 'cyan' | 'purple' | 'pink'The color palette of the component |
size | 'md' | 'xs' | 'sm' | 'md' | 'lg'The size of the component |
variant | 'outline' | 'outline' | 'subtle' | 'flushed'The variant of the component |
as | React.ElementTypeThe underlying element to render. | |
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
unstyled | booleanWhether to remove the component's style. | |
allowMouseWheel | booleanWhether to allow mouse wheel to change the value | |
defaultValue | stringThe initial value of the input when rendered. Use when you don't need to control the value of the input. | |
disabled | booleanWhether the number input is disabled. | |
form | stringThe associate form of the input element. | |
formatOptions | NumberFormatOptionsThe options to pass to the `Intl.NumberFormat` constructor | |
id | stringThe unique identifier of the machine. | |
ids | Partial<{
root: string
label: string
input: string
incrementTrigger: string
decrementTrigger: string
scrubber: string
}>The ids of the elements in the number input. Useful for composition. | |
invalid | booleanWhether the number input value is invalid. | |
name | stringThe name attribute of the number input. Useful for form submission. | |
onFocusChange | (details: FocusChangeDetails) => voidFunction invoked when the number input is focused | |
onValueChange | (details: ValueChangeDetails) => voidFunction invoked when the value changes | |
onValueInvalid | (details: ValueInvalidDetails) => voidFunction invoked when the value overflows or underflows the min/max range | |
readOnly | booleanWhether the number input is readonly | |
required | booleanWhether the number input is required | |
translations | IntlTranslationsSpecifies the localized strings that identifies the accessibility elements and their states | |
value | stringThe controlled value of the input |
Explorer
Explore the NumberInput component parts interactively. Click on parts in the
sidebar to highlight them in the preview.
Adjust a Number
Try using the arrows, typing directly, or dragging the scrubber to change the value.
Enter a number between 1 and 100.
Component Anatomy
Hover to highlight, click to select parts
root
label
input
control
valueText
incrementTrigger
decrementTrigger
scrubber
number-input.recipe.ts