# Number Input

**A numeric input component with increment and decrement controls.**

**Reference:** [View Source](https://github.com/jramke/fluid-primitives/tree/main/Resources/Private/Primitives/NumberInput) · [Zag.js Docs](https://zagjs.com/components/react/number-input)

**NumberInputExamples.html**

```html
<ui:numberInput.root defaultValue="0">
    <ui:numberInput.scrubber>
        <ui:numberInput.label>Quantity</ui:numberInput.label>
    </ui:numberInput.scrubber>
    <ui:numberInput.control>
        <ui:numberInput.decrementTrigger />
        <ui:numberInput.input />
        <ui:numberInput.incrementTrigger />
    </ui:numberInput.control>
</ui:numberInput.root>
```

## Features

- Based on the spinbutton pattern
- Supports using the scroll wheel to increment and decrement the value
- Handles floating point rounding errors when incrementing, decrementing, and snapping to step
- Supports pressing and holding the spin buttons to continuously increment or decrement
- Supports rounding value to specific number of fraction digits
- Support for scrubbing interaction
- Automatically sets the locale based on Site Language

## Anatomy

```html
<primitives:numberInput.root>
    <primitives:numberInput.label />
    <primitives:numberInput.control>
        <primitives:numberInput.decrementTrigger />
        <primitives:numberInput.input />
        <primitives:numberInput.incrementTrigger />
    </primitives:numberInput.control>
    <primitives:numberInput.scrubber />
    <primitives:numberInput.valueText />
</primitives:numberInput.root>
```

## Installation

```bash
typo3 ui:add number-input
```

Or copy the files manually from GitHub (https://github.com/jramke/fluid-primitives/tree/main/Resources/Private/Registry/NumberInput) into your project.

Read more about installing [Components and Primitives](/docs/core-concepts/primitives.md).

## Examples

### With Min/Max Constraints

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.

**NumberInputExamples.html**

```html
<ui:numberInput.root min="0" max="100" step="5" defaultValue="50">
    <ui:numberInput.label>Percentage</ui:numberInput.label>
    <ui:numberInput.control>
        <ui:numberInput.decrementTrigger />
        <ui:numberInput.input />
        <ui:numberInput.incrementTrigger />
    </ui:numberInput.control>
</ui:numberInput.root>

```

### With Format Options

You can format the input value to be rounded to specific decimal points or to be displayed as a currency by passing an object in shape of [Intl.NumberFormatOptions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat). Note that this is a client-only API so the initial value rendered on the server will not be formatted.

**NumberInputExamples.html**

```html
<ui:numberInput.root formatOptions="{style: 'currency', currency: 'USD'}" defaultValue="9.99">
    <ui:numberInput.label>Price</ui:numberInput.label>
    <ui:numberInput.control>
        <ui:numberInput.decrementTrigger />
        <ui:numberInput.input />
        <ui:numberInput.incrementTrigger />
    </ui:numberInput.control>
</ui:numberInput.root>

```

### With Scrubber

The scrubber allows users to change the value by clicking and dragging horizontally.

**NumberInputExamples.html**

```html
<ui:numberInput.root defaultValue="50">
    <ui:numberInput.scrubber>
        <ui:numberInput.label>Drag to adjust</ui:numberInput.label>
    </ui:numberInput.scrubber>
    <ui:numberInput.control>
        <ui:numberInput.decrementTrigger />
        <ui:numberInput.input />
        <ui:numberInput.incrementTrigger />
    </ui:numberInput.control>
</ui:numberInput.root>

```

### Mouse Wheel Support

Enable changing the value with the mouse wheel when the input is focused.

**NumberInputExamples.html**

```html
<ui:numberInput.root allowMouseWheel="{true}" defaultValue="0">
    <ui:numberInput.label>Scroll to change</ui:numberInput.label>
    <ui:numberInput.control>
        <ui:numberInput.decrementTrigger />
        <ui:numberInput.input />
        <ui:numberInput.incrementTrigger />
    </ui:numberInput.control>
</ui:numberInput.root>

```

### Localization

Default increment and decrement labels are shipped via XLF and follow the current Site Language. For per-template overrides, pass translated strings through the `translations` prop.

```html
<f:variable
    name="numberInputTranslations"
    value="{
        incrementLabel: '{f:translate(key: \'LLL:EXT:site_package/Resources/Private/Language/locallang.xlf:forms.quantity.increase\')}',
        decrementLabel: '{f:translate(key: \'LLL:EXT:site_package/Resources/Private/Language/locallang.xlf:forms.quantity.decrease\')}'
    }"
/>

<ui:numberInput.root translations="{numberInputTranslations}"> ... </ui:numberInput.root>
```

## API Reference

### numberInput.root

Provides shared number input state and wraps all related parts. Renders a `<div>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `disabled` | `boolean` | No | `-` | Whether the number input is disabled. Inherited from a surrounding field when available. |
| `invalid` | `boolean` | No | `-` | Whether the number input value is invalid. Inherited from a surrounding field when available. |
| `required` | `boolean` | No | `-` | Whether the number input is required. Inherited from a surrounding field when available. |
| `readOnly` | `boolean` | No | `-` | Whether the number input is readonly. Inherited from a surrounding field when available. |
| `name` | `string` | No | `-` | The name attribute of the number input. Useful for form submission. Inherited from a surrounding field when available. |
| `form` | `string` | No | `-` | The associate form of the input element. |
| `defaultValue` | `string` | No | `''` | The initial value of the input when rendered. Use when you don't need to control the value of the input. Inherited from a surrounding field when available. |
| `min` | `float` | No | `-` | The minimum value of the number input. |
| `max` | `float` | No | `-` | The maximum value of the number input. |
| `step` | `float` | No | `-` | The amount to increment or decrement the value by. |
| `smallStep` | `float` | No | `-` | The amount to increment or decrement the value by when the `Alt` key is held. Defaults to `step / 10`. |
| `largeStep` | `float` | No | `-` | The amount to increment or decrement the value by when the `Shift` key is held. Defaults to `10 * step`. |
| `allowMouseWheel` | `boolean` | No | `-` | Whether to allow mouse wheel to change the value. |
| `allowOverflow` | `boolean` | No | `false` | Whether to allow the value overflow the min/max range. |
| `clampValueOnBlur` | `boolean` | No | `true` | Whether to clamp the value when the input loses focus (blur). |
| `focusInputOnChange` | `boolean` | No | `true` | Whether to focus input when the value changes. |
| `spinOnPress` | `boolean` | No | `true` | Whether to spin the value when the increment/decrement button is pressed. |
| `formatOptions` | `array` | No | `-` | The options to pass to the `Intl.NumberFormat` constructor. |
| `inputMode` | `Enum\NumberInputMode` | No | `Decimal` | Hints at the type of data that might be entered by the user and the keyboard shown on mobile devices. |
| `pattern` | `string` | No | `'-?[0-9]*(.[0-9]+)?'` | The pattern used to check the `<input>` element's value against. |
| `translations` | `array` | No | `-` | Specifies the localized strings that identify the accessibility elements and their states. Use `f:translate` for per-template localization overrides when needed. |
| `locale` | `string` | No | `-` | The current locale. Inherited from the site's language. |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `rootId` | `string` | No | `-` | The root ID of the component, used for hydration and identification. |
| `ids` | `array` | No | `[]` | The IDs of of the component parts for composition. |
| `autoMount` | `boolean` | No | `true` | Whether the client initializes the component on its own. Set it to false to mount it yourself with `mount()` |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-number-input-root` | <uid> |
| `data-disabled` | Present when disabled |
| `data-focus` | Present when focused |
| `data-invalid` | Present when invalid |
| `data-scrubbing` |  |

### numberInput.label

Labels the number input. Renders a `<label>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-number-input-label` | <uid> |
| `data-disabled` | Present when disabled |
| `data-focus` | Present when focused |
| `data-invalid` | Present when invalid |
| `data-required` | Present when required |
| `data-scrubbing` |  |

### numberInput.control

Groups the input and stepper triggers. Renders a `<div>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-number-input-control` | <uid> |
| `data-focus` | Present when focused |
| `data-disabled` | Present when disabled |
| `data-invalid` | Present when invalid |
| `data-scrubbing` |  |

### numberInput.input

Provides the editable spinbutton input. Renders an `<input>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-number-input-input` | <uid> |
| `data-invalid` | Present when invalid |
| `data-disabled` | Present when disabled |
| `data-scrubbing` |  |

### numberInput.incrementTrigger

Increases the current value. Renders a `<button>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-number-input-increment-trigger` | <uid> |
| `data-disabled` | Present when disabled |
| `data-scrubbing` |  |

### numberInput.decrementTrigger

Decreases the current value. Renders a `<button>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-number-input-decrement-trigger` | <uid> |
| `data-disabled` | Present when disabled |
| `data-scrubbing` |  |

### numberInput.scrubber

Allows changing the value by dragging. Renders a `<div>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-number-input-scrubber` | <uid> |
| `data-disabled` | Present when disabled |
| `data-scrubbing` |  |

### numberInput.valueText

Displays the formatted value as text. Renders a `<span>` element.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `attributes` | `array` | No | `[]` | Additional attributes that should be rendered on the component where ui:attributes is used. |
| `asChild` | `boolean` | No | `-` | If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props. |
| `class` | `string` | No | `-` | The CSS class(es) to be applied to the component. |

#### Rendered data attributes

| Attribute | Description |
| --- | --- |
| `data-number-input-value-text` | <uid> |
| `data-disabled` | Present when disabled |
| `data-invalid` | Present when invalid |
| `data-focus` | Present when focused |
| `data-scrubbing` |  |

### Machine JavaScript API

| Name | Type | Description |
| --- | --- | --- |
| `focused` | `boolean` | Whether the input is focused. |
| `scrubbing` | `boolean` | Whether the input is being scrubbed. |
| `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. |
| `getRootState` | `() => RootState` | Returns the state of the root. |
| `getInputState` | `() => InputState` | Returns the state of the input. |
| `getDecrementTriggerState` | `() => DecrementTriggerState` | Returns the state of the decrement trigger. |
| `getIncrementTriggerState` | `() => IncrementTriggerState` | Returns the state of the increment trigger. |

### Accessibility

| Key | Description |
| --- | --- |
| `ArrowUp`  | Increments the value of the number input by a predefined step. |
| `ArrowDown`  | Decrements the value of the number input by a predefined step. |
| `Shift + ArrowUp`  | Increments the value of the number input by the `largeStep` amount. |
| `Shift + ArrowDown`  | Decrements the value of the number input by the `largeStep` amount. |
| `Alt + ArrowUp`  | Increments the value of the number input by the `smallStep` amount. |
| `Alt + ArrowDown`  | Decrements the value of the number input by the `smallStep` amount. |
| `Home`  | Sets the value of the number input to its minimum allowed value. |
| `End`  | Sets the value of the number input to its maximum allowed value. |
| `Enter`  | Submits the value entered in the number input. |
