# Number Input
URL: https://ark-ui.com/docs/components/number-input
Source: https://raw.githubusercontent.com/chakra-ui/ark/refs/heads/main/website/src/content/pages/components/number-input.mdx
A field that allows user input of numeric values.
---
## Anatomy
```tsx
```
## Examples
**Example: basic**
```ripple
import { NumberInput } from 'ark-ripple/number-input';
import { ChevronUp, ChevronDown } from 'lucide-ripple';
import styles from 'styles/number-input.module.css';
export component Basic() {
{'Label'}
}
```
### Min and Max
Pass the `min` prop or `max` prop to set an upper and lower limit for the input. By default, the input will restrict the
value to stay within the specified range.
**Example: min-max**
```ripple
import { NumberInput } from 'ark-ripple/number-input';
import { ChevronUp, ChevronDown } from 'lucide-ripple';
import styles from 'styles/number-input.module.css';
export component MinMax() {
{'Label'}
}
```
> To allow values outside the min/max range, set `clampValueOnBlur` to `false`.
### Precision
In some cases, you might need the value to be rounded to specific decimal points. Set the `formatOptions` and provide
`Intl.NumberFormatOptions` such as `maximumFractionDigits` or `minimumFractionDigits`.
**Example: fraction-digits**
```ripple
import { NumberInput } from 'ark-ripple/number-input';
import { ChevronUp, ChevronDown } from 'lucide-ripple';
import styles from 'styles/number-input.module.css';
export component FractionDigits() {
{'Label'}
}
```
### Scrubbing
The NumberInput supports the scrubber interaction pattern. To use this pattern, render the `NumberInput.Scrubber`
component. It uses the Pointer lock API and tracks the pointer movement. It also renders a virtual cursor which mimics
the real cursor's pointer.
**Example: scrubber**
```ripple
import { NumberInput } from 'ark-ripple/number-input';
import { ChevronUp, ChevronDown, ArrowLeftRight } from 'lucide-ripple';
import styles from 'styles/number-input.module.css';
export component Scrubber() {
{'Label'}
}
```
### Mouse Wheel
The NumberInput exposes a way to increment/decrement the value using the mouse wheel event. To activate this, set the
`allowMouseWheel` prop to `true`.
**Example: mouse-wheel**
```ripple
import { NumberInput } from 'ark-ripple/number-input';
import { ChevronUp, ChevronDown } from 'lucide-ripple';
import styles from 'styles/number-input.module.css';
export component MouseWheel() {
{'Label'}
}
```
### Formatting
To apply custom formatting to the input's value, set the `formatOptions` and provide `Intl.NumberFormatOptions` such as
`style` and `currency`.
**Example: formatting**
```ripple
import { NumberInput } from 'ark-ripple/number-input';
import { ChevronUp, ChevronDown } from 'lucide-ripple';
import styles from 'styles/number-input.module.css';
export component Formatting() {
{'Label'}
}
```
### Field
The `Field` component helps manage form-related state and accessibility attributes of a number input. It includes
handling ARIA labels, helper text, and error text to ensure proper accessibility.
**Example: with-field**
```ripple
import { Field } from 'ark-ripple/field';
import { NumberInput } from 'ark-ripple/number-input';
import { ChevronUp, ChevronDown } from 'lucide-ripple';
import field from 'styles/field.module.css';
import styles from 'styles/number-input.module.css';
export component WithField() {
{'Label'}
{'Additional Info'}{'Error Info'}
}
```
### Root Provider
An alternative way to control the number input is to use the `RootProvider` component and the `useNumberInput` hook.
This way you can access the state and methods from outside the component.
**Example: root-provider**
```ripple
import { NumberInput, useNumberInput } from 'ark-ripple/number-input';
import { ChevronUp, ChevronDown } from 'lucide-ripple';
import styles from 'styles/number-input.module.css';
export component RootProvider() {
const numberInput = useNumberInput();
{'Label'}
}
```
## Guides
### Scrubber
The `NumberInput.Scrubber` component provides an interactive scrub area that allows users to drag to change the input
value. It renders as a `
` element and displays a custom cursor element during scrubbing interactions.
This component utilizes the [Pointer Lock API](https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API) for
smooth dragging interactions.
> **Note:** Browsers may show a notification when the Pointer Lock API is activated. The scrubber is automatically
> disabled in Safari to prevent layout shifts.
### Controlled
When controlling the NumberInput component, it's recommended to use string values instead of converting to numbers. This
is especially important when using `formatOptions` for currency or locale-specific formatting.
```tsx
const [value, setValue] = useState('0')
setValue(details.value)}>
{/* ... */}
```
Converting values to numbers can cause issues with locale-specific formatting, particularly for currencies that use
different decimal and thousands separators (e.g., `1.523,30` vs `1,523.30`). By keeping values as strings, you preserve
the correct formatting and avoid parsing issues.
If you need to submit a numeric value in your form, use a hidden input that reads `valueAsNumber` from
`NumberInput.Context`:
```tsx
setValue(details.value)}>
{(context) => }
```
## API Reference
### Props
**Component API Reference**
**Root Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `allowMouseWheel` | `boolean` | No | Whether to allow mouse wheel to change the value |
| `allowOverflow` | `boolean` | No | Whether to allow the value overflow the min/max range |
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `clampValueOnBlur` | `boolean` | No | Whether to clamp the value when the input loses focus (blur) |
| `defaultValue` | `string` | No | The initial value of the input when rendered.
Use when you don't need to control the value of the input. |
| `disabled` | `boolean` | No | Whether the number input is disabled. |
| `focusInputOnChange` | `boolean` | No | Whether to focus input when the value changes |
| `form` | `string` | No | The associate form of the input element. |
| `formatOptions` | `NumberFormatOptions` | No | The options to pass to the `Intl.NumberFormat` constructor |
| `id` | `string` | No | The unique identifier of the machine. |
| `ids` | `Partial<{
root: string
label: string
input: string
incrementTrigger: string
decrementTrigger: string
scrubber: string
}>` | No | The ids of the elements in the number input. Useful for composition. |
| `inputMode` | `InputMode` | No | Hints 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 |
| `invalid` | `boolean` | No | Whether the number input value is invalid. |
| `locale` | `string` | No | The current locale. Based on the BCP 47 definition. |
| `max` | `number` | No | The maximum value of the number input |
| `min` | `number` | No | The minimum value of the number input |
| `name` | `string` | No | The name attribute of the number input. Useful for form submission. |
| `onFocusChange` | `(details: FocusChangeDetails) => void` | No | Function invoked when the number input is focused |
| `onValueChange` | `(details: ValueChangeDetails) => void` | No | Function invoked when the value changes |
| `onValueCommit` | `(details: ValueChangeDetails) => void` | No | Function invoked when the value is committed (when the input is blurred or the Enter key is pressed) |
| `onValueInvalid` | `(details: ValueInvalidDetails) => void` | No | Function invoked when the value overflows or underflows the min/max range |
| `pattern` | `string` | No | The pattern used to check the element's value against |
| `readOnly` | `boolean` | No | Whether the number input is readonly |
| `required` | `boolean` | No | Whether the number input is required |
| `spinOnPress` | `boolean` | No | Whether to spin the value when the increment/decrement button is pressed |
| `step` | `number` | No | The amount to increment or decrement the value by |
| `translations` | `IntlTranslations` | No | Specifies the localized strings that identifies the accessibility elements and their states |
| `value` | `string` | No | The controlled value of the input |
**Root Data Attributes:**
| Attribute | Value |
|-----------|-------|
| `[data-scope]` | number-input |
| `[data-part]` | root |
| `[data-disabled]` | Present when disabled |
| `[data-focus]` | Present when focused |
| `[data-invalid]` | Present when invalid |
| `[data-scrubbing]` | |
**Control Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
**Control Data Attributes:**
| Attribute | Value |
|-----------|-------|
| `[data-scope]` | number-input |
| `[data-part]` | control |
| `[data-focus]` | Present when focused |
| `[data-disabled]` | Present when disabled |
| `[data-invalid]` | Present when invalid |
| `[data-scrubbing]` | |
**DecrementTrigger Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
**DecrementTrigger Data Attributes:**
| Attribute | Value |
|-----------|-------|
| `[data-scope]` | number-input |
| `[data-part]` | decrement-trigger |
| `[data-disabled]` | Present when disabled |
| `[data-scrubbing]` | |
**IncrementTrigger Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
**IncrementTrigger Data Attributes:**
| Attribute | Value |
|-----------|-------|
| `[data-scope]` | number-input |
| `[data-part]` | increment-trigger |
| `[data-disabled]` | Present when disabled |
| `[data-scrubbing]` | |
**Input Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
**Input Data Attributes:**
| Attribute | Value |
|-----------|-------|
| `[data-scope]` | number-input |
| `[data-part]` | input |
| `[data-invalid]` | Present when invalid |
| `[data-disabled]` | Present when disabled |
| `[data-scrubbing]` | |
**Label Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
**Label Data Attributes:**
| Attribute | Value |
|-----------|-------|
| `[data-scope]` | number-input |
| `[data-part]` | label |
| `[data-disabled]` | Present when disabled |
| `[data-focus]` | Present when focused |
| `[data-invalid]` | Present when invalid |
| `[data-required]` | Present when required |
| `[data-scrubbing]` | |
**RootProvider Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `value` | `UseNumberInputReturn` | Yes | |
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
**Scrubber Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
**Scrubber Data Attributes:**
| Attribute | Value |
|-----------|-------|
| `[data-scope]` | number-input |
| `[data-part]` | scrubber |
| `[data-disabled]` | Present when disabled |
| `[data-scrubbing]` | |
**ValueText Props:**
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
**ValueText Data Attributes:**
| Attribute | Value |
|-----------|-------|
| `[data-scope]` | number-input |
| `[data-part]` | value-text |
| `[data-disabled]` | Present when disabled |
| `[data-invalid]` | Present when invalid |
| `[data-focus]` | Present when focused |
| `[data-scrubbing]` | |
### Context
**API:**
| Property | Type | Description |
|----------|------|-------------|
| `focused` | `boolean` | Whether the input is focused. |
| `invalid` | `boolean` | Whether the input is invalid. |
| `empty` | `boolean` | Whether the input value is empty. |
| `value` | `string` | The formatted value of the input. |
| `valueAsNumber` | `number` | The value of the input as a number. |
| `setValue` | `(value: number) => void` | Function to set the value of the input. |
| `clearValue` | `VoidFunction` | Function to clear the value of the input. |
| `increment` | `VoidFunction` | Function to increment the value of the input by the step. |
| `decrement` | `VoidFunction` | Function to decrement the value of the input by the step. |
| `setToMax` | `VoidFunction` | Function to set the value of the input to the max. |
| `setToMin` | `VoidFunction` | Function to set the value of the input to the min. |
| `focus` | `VoidFunction` | Function to focus the input. |
## Accessibility
Complies with the [Spinbutton WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/spinbutton/).
### Keyboard Support