# 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.

---

<ComponentPreview id="NumberInput" />

## Anatomy

<Anatomy id="number-input" />

```tsx
<NumberInput.Root>
  <NumberInput.Label />
  <NumberInput.Scrubber />
  <NumberInput.Control>
    <NumberInput.Input />
    <NumberInput.IncrementTrigger />
    <NumberInput.DecrementTrigger />
  </NumberInput.Control>
</NumberInput.Root>
```

## Examples

**Example: basic**

#### React

```tsx
import { NumberInput } from '@ark-ui/react/number-input'
import { ChevronDownIcon, ChevronUpIcon } from 'lucide-react'
import styles from 'styles/number-input.module.css'

export const Basic = () => (
  <NumberInput.Root className={styles.Root}>
    <NumberInput.Label className={styles.Label}>Label</NumberInput.Label>
    <NumberInput.Control className={styles.Control}>
      <NumberInput.Input className={styles.Input} />
      <div className={styles.TriggerGroup}>
        <NumberInput.IncrementTrigger className={styles.IncrementTrigger}>
          <ChevronUpIcon />
        </NumberInput.IncrementTrigger>
        <NumberInput.DecrementTrigger className={styles.DecrementTrigger}>
          <ChevronDownIcon />
        </NumberInput.DecrementTrigger>
      </div>
    </NumberInput.Control>
  </NumberInput.Root>
)

```

#### Solid

```tsx
import { NumberInput } from '@ark-ui/solid/number-input'
import { ChevronDownIcon, ChevronUpIcon } from 'lucide-solid'
import styles from 'styles/number-input.module.css'

export const Basic = () => (
  <NumberInput.Root class={styles.Root}>
    <NumberInput.Label class={styles.Label}>Label</NumberInput.Label>
    <NumberInput.Control class={styles.Control}>
      <NumberInput.Input class={styles.Input} />
      <div class={styles.TriggerGroup}>
        <NumberInput.IncrementTrigger class={styles.IncrementTrigger}>
          <ChevronUpIcon />
        </NumberInput.IncrementTrigger>
        <NumberInput.DecrementTrigger class={styles.DecrementTrigger}>
          <ChevronDownIcon />
        </NumberInput.DecrementTrigger>
      </div>
    </NumberInput.Control>
  </NumberInput.Root>
)

```

#### Vue

```vue
<script setup lang="ts">
import { NumberInput } from '@ark-ui/vue/number-input'
import { ChevronDownIcon, ChevronUpIcon } from 'lucide-vue-next'
import styles from 'styles/number-input.module.css'
</script>

<template>
  <NumberInput.Root :class="styles.Root">
    <NumberInput.Label :class="styles.Label">Label</NumberInput.Label>
    <NumberInput.Control :class="styles.Control">
      <NumberInput.Input :class="styles.Input" />
      <div :class="styles.TriggerGroup">
        <NumberInput.IncrementTrigger :class="styles.IncrementTrigger">
          <ChevronUpIcon />
        </NumberInput.IncrementTrigger>
        <NumberInput.DecrementTrigger :class="styles.DecrementTrigger">
          <ChevronDownIcon />
        </NumberInput.DecrementTrigger>
      </div>
    </NumberInput.Control>
  </NumberInput.Root>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { NumberInput } from '@ark-ui/svelte/number-input'
  import { ChevronDownIcon, ChevronUpIcon } from 'lucide-svelte'
  import styles from 'styles/number-input.module.css'
</script>

<NumberInput.Root class={styles.Root}>
  <NumberInput.Label class={styles.Label}>Label</NumberInput.Label>
  <NumberInput.Control class={styles.Control}>
    <NumberInput.Input class={styles.Input} />
    <div class={styles.TriggerGroup}>
      <NumberInput.IncrementTrigger class={styles.IncrementTrigger}>
        <ChevronUpIcon />
      </NumberInput.IncrementTrigger>
      <NumberInput.DecrementTrigger class={styles.DecrementTrigger}>
        <ChevronDownIcon />
      </NumberInput.DecrementTrigger>
    </div>
  </NumberInput.Control>
</NumberInput.Root>

```

### 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**

#### React

```tsx
import { NumberInput } from '@ark-ui/react/number-input'
import { ChevronDownIcon, ChevronUpIcon } from 'lucide-react'
import styles from 'styles/number-input.module.css'

export const MinMax = () => (
  <NumberInput.Root className={styles.Root} min={0} max={10}>
    <NumberInput.Label className={styles.Label}>Label</NumberInput.Label>
    <NumberInput.Control className={styles.Control}>
      <NumberInput.Input className={styles.Input} />
      <div className={styles.TriggerGroup}>
        <NumberInput.IncrementTrigger className={styles.IncrementTrigger}>
          <ChevronUpIcon />
        </NumberInput.IncrementTrigger>
        <NumberInput.DecrementTrigger className={styles.DecrementTrigger}>
          <ChevronDownIcon />
        </NumberInput.DecrementTrigger>
      </div>
    </NumberInput.Control>
  </NumberInput.Root>
)

```

#### Solid

```tsx
import { NumberInput } from '@ark-ui/solid/number-input'
import { ChevronDownIcon, ChevronUpIcon } from 'lucide-solid'
import styles from 'styles/number-input.module.css'

export const MinMax = () => (
  <NumberInput.Root class={styles.Root} min={0} max={10}>
    <NumberInput.Label class={styles.Label}>Label</NumberInput.Label>
    <NumberInput.Control class={styles.Control}>
      <NumberInput.Input class={styles.Input} />
      <div class={styles.TriggerGroup}>
        <NumberInput.IncrementTrigger class={styles.IncrementTrigger}>
          <ChevronUpIcon />
        </NumberInput.IncrementTrigger>
        <NumberInput.DecrementTrigger class={styles.DecrementTrigger}>
          <ChevronDownIcon />
        </NumberInput.DecrementTrigger>
      </div>
    </NumberInput.Control>
  </NumberInput.Root>
)

```

#### Vue

```vue
<script setup lang="ts">
import { NumberInput } from '@ark-ui/vue/number-input'
import { ChevronDownIcon, ChevronUpIcon } from 'lucide-vue-next'
import styles from 'styles/number-input.module.css'
</script>

<template>
  <NumberInput.Root :class="styles.Root" :min="0" :max="10">
    <NumberInput.Label :class="styles.Label">Label</NumberInput.Label>
    <NumberInput.Control :class="styles.Control">
      <NumberInput.Input :class="styles.Input" />
      <div :class="styles.TriggerGroup">
        <NumberInput.IncrementTrigger :class="styles.IncrementTrigger">
          <ChevronUpIcon />
        </NumberInput.IncrementTrigger>
        <NumberInput.DecrementTrigger :class="styles.DecrementTrigger">
          <ChevronDownIcon />
        </NumberInput.DecrementTrigger>
      </div>
    </NumberInput.Control>
  </NumberInput.Root>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { NumberInput } from '@ark-ui/svelte/number-input'
  import { ChevronDownIcon, ChevronUpIcon } from 'lucide-svelte'
  import styles from 'styles/number-input.module.css'
</script>

<NumberInput.Root class={styles.Root} min={0} max={10}>
  <NumberInput.Label class={styles.Label}>Label</NumberInput.Label>
  <NumberInput.Control class={styles.Control}>
    <NumberInput.Input class={styles.Input} />
    <div class={styles.TriggerGroup}>
      <NumberInput.IncrementTrigger class={styles.IncrementTrigger}>
        <ChevronUpIcon />
      </NumberInput.IncrementTrigger>
      <NumberInput.DecrementTrigger class={styles.DecrementTrigger}>
        <ChevronDownIcon />
      </NumberInput.DecrementTrigger>
    </div>
  </NumberInput.Control>
</NumberInput.Root>

```

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

#### React

```tsx
import { NumberInput } from '@ark-ui/react/number-input'
import { ChevronDownIcon, ChevronUpIcon } from 'lucide-react'
import styles from 'styles/number-input.module.css'

export const FractionDigits = () => (
  <NumberInput.Root
    className={styles.Root}
    formatOptions={{ minimumFractionDigits: 2, maximumFractionDigits: 3 }}
    defaultValue="1.00"
  >
    <NumberInput.Label className={styles.Label}>Label</NumberInput.Label>
    <NumberInput.Control className={styles.Control}>
      <NumberInput.Input className={styles.Input} />
      <div className={styles.TriggerGroup}>
        <NumberInput.IncrementTrigger className={styles.IncrementTrigger}>
          <ChevronUpIcon />
        </NumberInput.IncrementTrigger>
        <NumberInput.DecrementTrigger className={styles.DecrementTrigger}>
          <ChevronDownIcon />
        </NumberInput.DecrementTrigger>
      </div>
    </NumberInput.Control>
  </NumberInput.Root>
)

```

#### Solid

```tsx
import { NumberInput } from '@ark-ui/solid/number-input'
import { ChevronDownIcon, ChevronUpIcon } from 'lucide-solid'
import styles from 'styles/number-input.module.css'

export const FractionDigits = () => (
  <NumberInput.Root
    class={styles.Root}
    formatOptions={{ minimumFractionDigits: 2, maximumFractionDigits: 3 }}
    defaultValue="1.00"
  >
    <NumberInput.Label class={styles.Label}>Label</NumberInput.Label>
    <NumberInput.Control class={styles.Control}>
      <NumberInput.Input class={styles.Input} />
      <div class={styles.TriggerGroup}>
        <NumberInput.IncrementTrigger class={styles.IncrementTrigger}>
          <ChevronUpIcon />
        </NumberInput.IncrementTrigger>
        <NumberInput.DecrementTrigger class={styles.DecrementTrigger}>
          <ChevronDownIcon />
        </NumberInput.DecrementTrigger>
      </div>
    </NumberInput.Control>
  </NumberInput.Root>
)

```

#### Vue

```vue
<script setup lang="ts">
import { NumberInput } from '@ark-ui/vue/number-input'
import { ChevronDownIcon, ChevronUpIcon } from 'lucide-vue-next'
import styles from 'styles/number-input.module.css'
</script>

<template>
  <NumberInput.Root
    :class="styles.Root"
    :formatOptions="{ minimumFractionDigits: 2, maximumFractionDigits: 3 }"
    defaultValue="1.00"
  >
    <NumberInput.Label :class="styles.Label">Label</NumberInput.Label>
    <NumberInput.Control :class="styles.Control">
      <NumberInput.Input :class="styles.Input" />
      <div :class="styles.TriggerGroup">
        <NumberInput.IncrementTrigger :class="styles.IncrementTrigger">
          <ChevronUpIcon />
        </NumberInput.IncrementTrigger>
        <NumberInput.DecrementTrigger :class="styles.DecrementTrigger">
          <ChevronDownIcon />
        </NumberInput.DecrementTrigger>
      </div>
    </NumberInput.Control>
  </NumberInput.Root>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { NumberInput } from '@ark-ui/svelte/number-input'
  import { ChevronDownIcon, ChevronUpIcon } from 'lucide-svelte'
  import styles from 'styles/number-input.module.css'
</script>

<NumberInput.Root
  class={styles.Root}
  formatOptions={{ minimumFractionDigits: 2, maximumFractionDigits: 3 }}
  defaultValue="1.00"
>
  <NumberInput.Label class={styles.Label}>Label</NumberInput.Label>
  <NumberInput.Control class={styles.Control}>
    <NumberInput.Input class={styles.Input} />
    <div class={styles.TriggerGroup}>
      <NumberInput.IncrementTrigger class={styles.IncrementTrigger}>
        <ChevronUpIcon />
      </NumberInput.IncrementTrigger>
      <NumberInput.DecrementTrigger class={styles.DecrementTrigger}>
        <ChevronDownIcon />
      </NumberInput.DecrementTrigger>
    </div>
  </NumberInput.Control>
</NumberInput.Root>

```

### 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**

#### React

```tsx
import { NumberInput } from '@ark-ui/react/number-input'
import { ChevronDownIcon, ChevronUpIcon, ArrowLeftRightIcon } from 'lucide-react'
import styles from 'styles/number-input.module.css'

export const Scrubber = () => (
  <NumberInput.Root className={styles.Root} defaultValue="32">
    <NumberInput.Label className={styles.Label}>Label</NumberInput.Label>
    <NumberInput.Control className={styles.Control}>
      <NumberInput.Scrubber className={styles.Scrubber}>
        <ArrowLeftRightIcon />
      </NumberInput.Scrubber>
      <NumberInput.Input className={styles.Input} data-has-scrubber />
      <div className={styles.TriggerGroup}>
        <NumberInput.IncrementTrigger className={styles.IncrementTrigger}>
          <ChevronUpIcon />
        </NumberInput.IncrementTrigger>
        <NumberInput.DecrementTrigger className={styles.DecrementTrigger}>
          <ChevronDownIcon />
        </NumberInput.DecrementTrigger>
      </div>
    </NumberInput.Control>
  </NumberInput.Root>
)

```

#### Solid

```tsx
import { NumberInput } from '@ark-ui/solid/number-input'
import { ArrowLeftRightIcon, ChevronDownIcon, ChevronUpIcon } from 'lucide-solid'
import styles from 'styles/number-input.module.css'

export const Scrubber = () => (
  <NumberInput.Root class={styles.Root} defaultValue="32">
    <NumberInput.Label class={styles.Label}>Label</NumberInput.Label>
    <NumberInput.Control class={styles.Control}>
      <NumberInput.Scrubber class={styles.Scrubber}>
        <ArrowLeftRightIcon />
      </NumberInput.Scrubber>
      <NumberInput.Input class={styles.Input} data-has-scrubber />
      <div class={styles.TriggerGroup}>
        <NumberInput.IncrementTrigger class={styles.IncrementTrigger}>
          <ChevronUpIcon />
        </NumberInput.IncrementTrigger>
        <NumberInput.DecrementTrigger class={styles.DecrementTrigger}>
          <ChevronDownIcon />
        </NumberInput.DecrementTrigger>
      </div>
    </NumberInput.Control>
  </NumberInput.Root>
)

```

#### Vue

```vue
<script setup lang="ts">
import { NumberInput } from '@ark-ui/vue/number-input'
import { ArrowLeftRightIcon, ChevronDownIcon, ChevronUpIcon } from 'lucide-vue-next'
import styles from 'styles/number-input.module.css'
</script>

<template>
  <NumberInput.Root :class="styles.Root" defaultValue="32">
    <NumberInput.Label :class="styles.Label">Label</NumberInput.Label>
    <NumberInput.Control :class="styles.Control">
      <NumberInput.Scrubber :class="styles.Scrubber">
        <ArrowLeftRightIcon />
      </NumberInput.Scrubber>
      <NumberInput.Input :class="styles.Input" data-has-scrubber />
      <div :class="styles.TriggerGroup">
        <NumberInput.IncrementTrigger :class="styles.IncrementTrigger">
          <ChevronUpIcon />
        </NumberInput.IncrementTrigger>
        <NumberInput.DecrementTrigger :class="styles.DecrementTrigger">
          <ChevronDownIcon />
        </NumberInput.DecrementTrigger>
      </div>
    </NumberInput.Control>
  </NumberInput.Root>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { NumberInput } from '@ark-ui/svelte/number-input'
  import { ArrowLeftRightIcon, ChevronDownIcon, ChevronUpIcon } from 'lucide-svelte'
  import styles from 'styles/number-input.module.css'
</script>

<NumberInput.Root class={styles.Root} defaultValue="32">
  <NumberInput.Label class={styles.Label}>Label</NumberInput.Label>
  <NumberInput.Control class={styles.Control}>
    <NumberInput.Scrubber class={styles.Scrubber}>
      <ArrowLeftRightIcon />
    </NumberInput.Scrubber>
    <NumberInput.Input class={styles.Input} data-has-scrubber />
    <div class={styles.TriggerGroup}>
      <NumberInput.IncrementTrigger class={styles.IncrementTrigger}>
        <ChevronUpIcon />
      </NumberInput.IncrementTrigger>
      <NumberInput.DecrementTrigger class={styles.DecrementTrigger}>
        <ChevronDownIcon />
      </NumberInput.DecrementTrigger>
    </div>
  </NumberInput.Control>
</NumberInput.Root>

```

### 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**

#### React

```tsx
import { NumberInput } from '@ark-ui/react/number-input'
import { ChevronDownIcon, ChevronUpIcon } from 'lucide-react'
import styles from 'styles/number-input.module.css'

export const MouseWheel = () => (
  <NumberInput.Root className={styles.Root} allowMouseWheel>
    <NumberInput.Label className={styles.Label}>Label</NumberInput.Label>
    <NumberInput.Control className={styles.Control}>
      <NumberInput.Input className={styles.Input} />
      <div className={styles.TriggerGroup}>
        <NumberInput.IncrementTrigger className={styles.IncrementTrigger}>
          <ChevronUpIcon />
        </NumberInput.IncrementTrigger>
        <NumberInput.DecrementTrigger className={styles.DecrementTrigger}>
          <ChevronDownIcon />
        </NumberInput.DecrementTrigger>
      </div>
    </NumberInput.Control>
  </NumberInput.Root>
)

```

#### Solid

```tsx
import { NumberInput } from '@ark-ui/solid/number-input'
import { ChevronDownIcon, ChevronUpIcon } from 'lucide-solid'
import styles from 'styles/number-input.module.css'

export const MouseWheel = () => (
  <NumberInput.Root class={styles.Root} allowMouseWheel>
    <NumberInput.Label class={styles.Label}>Label</NumberInput.Label>
    <NumberInput.Control class={styles.Control}>
      <NumberInput.Input class={styles.Input} />
      <div class={styles.TriggerGroup}>
        <NumberInput.IncrementTrigger class={styles.IncrementTrigger}>
          <ChevronUpIcon />
        </NumberInput.IncrementTrigger>
        <NumberInput.DecrementTrigger class={styles.DecrementTrigger}>
          <ChevronDownIcon />
        </NumberInput.DecrementTrigger>
      </div>
    </NumberInput.Control>
  </NumberInput.Root>
)

```

#### Vue

```vue
<script setup lang="ts">
import { NumberInput } from '@ark-ui/vue/number-input'
import { ChevronDownIcon, ChevronUpIcon } from 'lucide-vue-next'
import styles from 'styles/number-input.module.css'
</script>

<template>
  <NumberInput.Root :class="styles.Root" allowMouseWheel>
    <NumberInput.Label :class="styles.Label">Label</NumberInput.Label>
    <NumberInput.Control :class="styles.Control">
      <NumberInput.Input :class="styles.Input" />
      <div :class="styles.TriggerGroup">
        <NumberInput.IncrementTrigger :class="styles.IncrementTrigger">
          <ChevronUpIcon />
        </NumberInput.IncrementTrigger>
        <NumberInput.DecrementTrigger :class="styles.DecrementTrigger">
          <ChevronDownIcon />
        </NumberInput.DecrementTrigger>
      </div>
    </NumberInput.Control>
  </NumberInput.Root>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { NumberInput } from '@ark-ui/svelte/number-input'
  import { ChevronDownIcon, ChevronUpIcon } from 'lucide-svelte'
  import styles from 'styles/number-input.module.css'
</script>

<NumberInput.Root class={styles.Root} allowMouseWheel>
  <NumberInput.Label class={styles.Label}>Label</NumberInput.Label>
  <NumberInput.Control class={styles.Control}>
    <NumberInput.Input class={styles.Input} />
    <div class={styles.TriggerGroup}>
      <NumberInput.IncrementTrigger class={styles.IncrementTrigger}>
        <ChevronUpIcon />
      </NumberInput.IncrementTrigger>
      <NumberInput.DecrementTrigger class={styles.DecrementTrigger}>
        <ChevronDownIcon />
      </NumberInput.DecrementTrigger>
    </div>
  </NumberInput.Control>
</NumberInput.Root>

```

### Formatting

To apply custom formatting to the input's value, set the `formatOptions` and provide `Intl.NumberFormatOptions` such as
`style` and `currency`.

**Example: formatting**

#### React

```tsx
import { NumberInput } from '@ark-ui/react/number-input'
import { ChevronDownIcon, ChevronUpIcon } from 'lucide-react'
import styles from 'styles/number-input.module.css'

export const Formatting = () => (
  <NumberInput.Root
    className={styles.Root}
    formatOptions={{
      style: 'currency',
      currency: 'USD',
    }}
  >
    <NumberInput.Label className={styles.Label}>Label</NumberInput.Label>
    <NumberInput.Control className={styles.Control}>
      <NumberInput.Input className={styles.Input} />
      <div className={styles.TriggerGroup}>
        <NumberInput.IncrementTrigger className={styles.IncrementTrigger}>
          <ChevronUpIcon />
        </NumberInput.IncrementTrigger>
        <NumberInput.DecrementTrigger className={styles.DecrementTrigger}>
          <ChevronDownIcon />
        </NumberInput.DecrementTrigger>
      </div>
    </NumberInput.Control>
  </NumberInput.Root>
)

```

#### Solid

```tsx
import { NumberInput } from '@ark-ui/solid/number-input'
import { ChevronDownIcon, ChevronUpIcon } from 'lucide-solid'
import styles from 'styles/number-input.module.css'

export const Formatting = () => (
  <NumberInput.Root
    class={styles.Root}
    formatOptions={{
      style: 'currency',
      currency: 'USD',
    }}
  >
    <NumberInput.Label class={styles.Label}>Label</NumberInput.Label>
    <NumberInput.Control class={styles.Control}>
      <NumberInput.Input class={styles.Input} />
      <div class={styles.TriggerGroup}>
        <NumberInput.IncrementTrigger class={styles.IncrementTrigger}>
          <ChevronUpIcon />
        </NumberInput.IncrementTrigger>
        <NumberInput.DecrementTrigger class={styles.DecrementTrigger}>
          <ChevronDownIcon />
        </NumberInput.DecrementTrigger>
      </div>
    </NumberInput.Control>
  </NumberInput.Root>
)

```

#### Vue

```vue
<script setup lang="ts">
import { NumberInput } from '@ark-ui/vue/number-input'
import { ChevronDownIcon, ChevronUpIcon } from 'lucide-vue-next'
import styles from 'styles/number-input.module.css'
</script>

<template>
  <NumberInput.Root :class="styles.Root" :formatOptions="{ style: 'currency', currency: 'USD' }">
    <NumberInput.Label :class="styles.Label">Label</NumberInput.Label>
    <NumberInput.Control :class="styles.Control">
      <NumberInput.Input :class="styles.Input" />
      <div :class="styles.TriggerGroup">
        <NumberInput.IncrementTrigger :class="styles.IncrementTrigger">
          <ChevronUpIcon />
        </NumberInput.IncrementTrigger>
        <NumberInput.DecrementTrigger :class="styles.DecrementTrigger">
          <ChevronDownIcon />
        </NumberInput.DecrementTrigger>
      </div>
    </NumberInput.Control>
  </NumberInput.Root>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { NumberInput } from '@ark-ui/svelte/number-input'
  import { ChevronDownIcon, ChevronUpIcon } from 'lucide-svelte'
  import styles from 'styles/number-input.module.css'
</script>

<NumberInput.Root
  class={styles.Root}
  formatOptions={{
    style: 'currency',
    currency: 'USD',
  }}
>
  <NumberInput.Label class={styles.Label}>Label</NumberInput.Label>
  <NumberInput.Control class={styles.Control}>
    <NumberInput.Input class={styles.Input} />
    <div class={styles.TriggerGroup}>
      <NumberInput.IncrementTrigger class={styles.IncrementTrigger}>
        <ChevronUpIcon />
      </NumberInput.IncrementTrigger>
      <NumberInput.DecrementTrigger class={styles.DecrementTrigger}>
        <ChevronDownIcon />
      </NumberInput.DecrementTrigger>
    </div>
  </NumberInput.Control>
</NumberInput.Root>

```

### 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**

#### React

```tsx
import { Field } from '@ark-ui/react/field'
import { NumberInput } from '@ark-ui/react/number-input'
import { ChevronDownIcon, ChevronUpIcon } from 'lucide-react'
import field from 'styles/field.module.css'
import styles from 'styles/number-input.module.css'

export const WithField = () => (
  <Field.Root className={field.Root}>
    <NumberInput.Root className={styles.Root}>
      <NumberInput.Label className={styles.Label}>Label</NumberInput.Label>
      <NumberInput.Control className={styles.Control}>
        <NumberInput.Input className={styles.Input} />
        <div className={styles.TriggerGroup}>
          <NumberInput.IncrementTrigger className={styles.IncrementTrigger}>
            <ChevronUpIcon />
          </NumberInput.IncrementTrigger>
          <NumberInput.DecrementTrigger className={styles.DecrementTrigger}>
            <ChevronDownIcon />
          </NumberInput.DecrementTrigger>
        </div>
      </NumberInput.Control>
    </NumberInput.Root>
    <Field.HelperText className={field.HelperText}>Additional Info</Field.HelperText>
    <Field.ErrorText className={field.ErrorText}>Error Info</Field.ErrorText>
  </Field.Root>
)

```

#### Solid

```tsx
import { Field } from '@ark-ui/solid/field'
import { NumberInput } from '@ark-ui/solid/number-input'
import { ChevronDownIcon, ChevronUpIcon } from 'lucide-solid'
import field from 'styles/field.module.css'
import styles from 'styles/number-input.module.css'

export const WithField = () => (
  <Field.Root class={field.Root}>
    <NumberInput.Root class={styles.Root}>
      <NumberInput.Label class={styles.Label}>Label</NumberInput.Label>
      <NumberInput.Control class={styles.Control}>
        <NumberInput.Input class={styles.Input} />
        <div class={styles.TriggerGroup}>
          <NumberInput.IncrementTrigger class={styles.IncrementTrigger}>
            <ChevronUpIcon />
          </NumberInput.IncrementTrigger>
          <NumberInput.DecrementTrigger class={styles.DecrementTrigger}>
            <ChevronDownIcon />
          </NumberInput.DecrementTrigger>
        </div>
      </NumberInput.Control>
    </NumberInput.Root>
    <Field.HelperText class={field.HelperText}>Additional Info</Field.HelperText>
    <Field.ErrorText class={field.ErrorText}>Error Info</Field.ErrorText>
  </Field.Root>
)

```

#### Vue

```vue
<script setup lang="ts">
import { Field } from '@ark-ui/vue/field'
import { NumberInput } from '@ark-ui/vue/number-input'
import { ChevronDownIcon, ChevronUpIcon } from 'lucide-vue-next'
import field from 'styles/field.module.css'
import styles from 'styles/number-input.module.css'
</script>

<template>
  <Field.Root :class="field.Root">
    <NumberInput.Root :class="styles.Root">
      <NumberInput.Label :class="styles.Label">Label</NumberInput.Label>
      <NumberInput.Control :class="styles.Control">
        <NumberInput.Input :class="styles.Input" />
        <div :class="styles.TriggerGroup">
          <NumberInput.IncrementTrigger :class="styles.IncrementTrigger">
            <ChevronUpIcon />
          </NumberInput.IncrementTrigger>
          <NumberInput.DecrementTrigger :class="styles.DecrementTrigger">
            <ChevronDownIcon />
          </NumberInput.DecrementTrigger>
        </div>
      </NumberInput.Control>
    </NumberInput.Root>
    <Field.HelperText :class="field.HelperText">Additional Info</Field.HelperText>
    <Field.ErrorText :class="field.ErrorText">Error Info</Field.ErrorText>
  </Field.Root>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { Field } from '@ark-ui/svelte/field'
  import { NumberInput } from '@ark-ui/svelte/number-input'
  import { ChevronDownIcon, ChevronUpIcon } from 'lucide-svelte'
  import field from 'styles/field.module.css'
  import styles from 'styles/number-input.module.css'
</script>

<Field.Root class={field.Root}>
  <NumberInput.Root class={styles.Root}>
    <NumberInput.Label class={styles.Label}>Label</NumberInput.Label>
    <NumberInput.Control class={styles.Control}>
      <NumberInput.Input class={styles.Input} />
      <div class={styles.TriggerGroup}>
        <NumberInput.IncrementTrigger class={styles.IncrementTrigger}>
          <ChevronUpIcon />
        </NumberInput.IncrementTrigger>
        <NumberInput.DecrementTrigger class={styles.DecrementTrigger}>
          <ChevronDownIcon />
        </NumberInput.DecrementTrigger>
      </div>
    </NumberInput.Control>
  </NumberInput.Root>
  <Field.HelperText class={field.HelperText}>Additional Info</Field.HelperText>
  <Field.ErrorText class={field.ErrorText}>Error Info</Field.ErrorText>
</Field.Root>

```

### 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**

#### React

```tsx
import { NumberInput, useNumberInput } from '@ark-ui/react/number-input'
import { ChevronDownIcon, ChevronUpIcon } from 'lucide-react'
import styles from 'styles/number-input.module.css'

export const RootProvider = () => {
  const numberInput = useNumberInput()
  return (
    <div className="stack">
      <output>valueAsNumber: {numberInput.valueAsNumber}</output>
      <NumberInput.RootProvider className={styles.Root} value={numberInput}>
        <NumberInput.Label className={styles.Label}>Label</NumberInput.Label>
        <NumberInput.Control className={styles.Control}>
          <NumberInput.Input className={styles.Input} />
          <div className={styles.TriggerGroup}>
            <NumberInput.IncrementTrigger className={styles.IncrementTrigger}>
              <ChevronUpIcon />
            </NumberInput.IncrementTrigger>
            <NumberInput.DecrementTrigger className={styles.DecrementTrigger}>
              <ChevronDownIcon />
            </NumberInput.DecrementTrigger>
          </div>
        </NumberInput.Control>
      </NumberInput.RootProvider>
    </div>
  )
}

```

#### Solid

```tsx
import { NumberInput, useNumberInput } from '@ark-ui/solid/number-input'
import { ChevronDownIcon, ChevronUpIcon } from 'lucide-solid'
import styles from 'styles/number-input.module.css'

export const RootProvider = () => {
  const numberInput = useNumberInput()

  return (
    <div class="stack">
      <output>valueAsNumber: {numberInput().valueAsNumber}</output>
      <NumberInput.RootProvider class={styles.Root} value={numberInput}>
        <NumberInput.Label class={styles.Label}>Label</NumberInput.Label>
        <NumberInput.Control class={styles.Control}>
          <NumberInput.Input class={styles.Input} />
          <div class={styles.TriggerGroup}>
            <NumberInput.IncrementTrigger class={styles.IncrementTrigger}>
              <ChevronUpIcon />
            </NumberInput.IncrementTrigger>
            <NumberInput.DecrementTrigger class={styles.DecrementTrigger}>
              <ChevronDownIcon />
            </NumberInput.DecrementTrigger>
          </div>
        </NumberInput.Control>
      </NumberInput.RootProvider>
    </div>
  )
}

```

#### Vue

```vue
<script setup lang="ts">
import { NumberInput, useNumberInput } from '@ark-ui/vue/number-input'
import { ChevronDownIcon, ChevronUpIcon } from 'lucide-vue-next'
import styles from 'styles/number-input.module.css'

const numberInput = useNumberInput()
</script>

<template>
  <div class="stack">
    <output>valueAsNumber: {{ numberInput.valueAsNumber }}</output>
    <NumberInput.RootProvider :class="styles.Root" :value="numberInput">
      <NumberInput.Label :class="styles.Label">Label</NumberInput.Label>
      <NumberInput.Control :class="styles.Control">
        <NumberInput.Input :class="styles.Input" />
        <div :class="styles.TriggerGroup">
          <NumberInput.IncrementTrigger :class="styles.IncrementTrigger">
            <ChevronUpIcon />
          </NumberInput.IncrementTrigger>
          <NumberInput.DecrementTrigger :class="styles.DecrementTrigger">
            <ChevronDownIcon />
          </NumberInput.DecrementTrigger>
        </div>
      </NumberInput.Control>
    </NumberInput.RootProvider>
  </div>
</template>

```

#### Svelte

```svelte
<script lang="ts">
  import { NumberInput, useNumberInput } from '@ark-ui/svelte/number-input'
  import { ChevronDownIcon, ChevronUpIcon } from 'lucide-svelte'
  import styles from 'styles/number-input.module.css'

  const id = $props.id()
  const numberInput = useNumberInput({ id })
</script>

<div class="stack">
  <output>valueAsNumber: {numberInput().valueAsNumber}</output>
  <NumberInput.RootProvider class={styles.Root} value={numberInput}>
    <NumberInput.Label class={styles.Label}>Label</NumberInput.Label>
    <NumberInput.Control class={styles.Control}>
      <NumberInput.Input class={styles.Input} />
      <div class={styles.TriggerGroup}>
        <NumberInput.IncrementTrigger class={styles.IncrementTrigger}>
          <ChevronUpIcon />
        </NumberInput.IncrementTrigger>
        <NumberInput.DecrementTrigger class={styles.DecrementTrigger}>
          <ChevronDownIcon />
        </NumberInput.DecrementTrigger>
      </div>
    </NumberInput.Control>
  </NumberInput.RootProvider>
</div>

```

## 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 `<div>` 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')

<NumberInput.Root value={value} onValueChange={(details) => setValue(details.value)}>
  {/* ... */}
</NumberInput.Root>
```

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
<NumberInput.Root value={value} onValueChange={(details) => setValue(details.value)}>
  <NumberInput.Input />
  <NumberInput.Context>
    {(context) => <input type="hidden" name="amount" value={context.valueAsNumber} />}
  </NumberInput.Context>
</NumberInput.Root>
```

## API Reference

### Props

**Component API Reference**

#### React

**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 <input> 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]` |  |


#### Solid

**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` | `(props: ParentProps<'div'>) => Element` | 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 <input> 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` | `(props: ParentProps<'div'>) => Element` | 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` | `(props: ParentProps<'button'>) => Element` | 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` | `(props: ParentProps<'button'>) => Element` | 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` | `(props: ParentProps<'input'>) => Element` | 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` | `(props: ParentProps<'label'>) => Element` | 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` | `(props: ParentProps<'div'>) => Element` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Scrubber Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `(props: ParentProps<'div'>) => Element` | 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` | `(props: ParentProps<'span'>) => Element` | 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]` |  |


#### Vue

**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` | `'text' | 'tel' | 'numeric' | 'decimal'` | 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 |
| `modelValue` | `string` | No | The v-model value of the number input |
| `name` | `string` | No | The name attribute of the number input. Useful for form submission. |
| `pattern` | `string` | No | The pattern used to check the <input> 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 |


**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` | `NumberInputApi<PropTypes>` | 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]` |  |


#### Svelte

**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` | `Snippet<[PropsFn<'div'>]>` | 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 <input> element's value against |
| `readOnly` | `boolean` | No | Whether the number input is readonly |
| `ref` | `Element` | No |  |
| `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]` |  |


**Context Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `render` | `Snippet<[UseNumberInputContext]>` | Yes |  |


**Control Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `ref` | `Element` | No |  |


**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` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `ref` | `Element` | No |  |


**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` | `Snippet<[PropsFn<'button'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `ref` | `Element` | No |  |


**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` | `Snippet<[PropsFn<'input'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `ref` | `Element` | No |  |


**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` | `Snippet<[PropsFn<'label'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `ref` | `Element` | No |  |


**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` | `Snippet<[PropsFn<'div'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `ref` | `Element` | No |  |


**Scrubber Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `Snippet<[PropsFn<'span'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `ref` | `Element` | No |  |


**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` | `Snippet<[PropsFn<'span'>]>` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `ref` | `Element` | No |  |


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

<KeyBindingsTable id="number-input" />