<script setup lang="ts">
import { NumberFieldDecrement, NumberFieldIncrement, NumberFieldInput, NumberFieldRoot } from 'akar';
</script>
<template>
<div class="akar-demo akar-demo-NumberField">
<NumberFieldRoot
id="age"
class="text-sm color-white"
:min="0"
:default-value="18"
>
<label for="age">Age</label>
<div class="bg-blackA7 border-blackA9 mt-1 border rounded-md flex items-center">
<NumberFieldDecrement class="p-2 disabled:opacity-20">
<PIcon name="i-lucide-minus" />
</NumberFieldDecrement>
<NumberFieldInput class="p-1 bg-transparent w-20 tabular-nums focus:outline-0" />
<NumberFieldIncrement class="p-2 disabled:opacity-20">
<PIcon name="i-lucide-plus" />
</NumberFieldIncrement>
</div>
</NumberFieldRoot>
</div>
</template>@import '../_colors/black-alpha.css';
@import '../_colors/grass.css';
@scope (.akar-demo-NumberField) {
/* reset */
button {
all: unset;
}
.CheckboxRoot {
background-color: white;
width: 25px;
height: 25px;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 2px 10px var(--black-a7);
}
.CheckboxRoot:hover {
background-color: var(--grass-3);
}
.CheckboxRoot:focus {
box-shadow: 0 0 0 2px black;
}
.CheckboxIndicator {
color: var(--grass-11);
}
}Features
- Full keyboard navigation.
- Can be controlled or uncontrolled.
- Support button hold and wheel event.
- Support numbering systems in different locale.
- Customizable formatting.
Installation
Install the number package.
pnpm add @internationalized/number
yarn add @internationalized/number
npm install @internationalized/number
bun add @internationalized/number
Install the component from your command line.
pnpm add akar
yarn add akar
npm install akar
bun add akar
Anatomy
Import all parts and piece them together.
<script setup>
import { NumberFieldDecrement, NumberFieldIncrement, NumberFieldInput, NumberFieldRoot } from 'akar';
</script>
<template>
<NumberFieldRoot>
<NumberFieldDecrement />
<NumberFieldInput />
<NumberFieldIncrement />
</NumberFieldRoot>
</template>
API Reference
Root
Contains all the parts of a number field. An input will also render when used within a form to ensure events propagate correctly.
| Prop | Default | Type |
|---|---|---|
as | "div" | AsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. | |
defaultValue | number | |
disabled | booleanWhen | |
disableWheelChange | booleanWhen | |
focusOnChange | true | booleanWhen |
formatOptions | Intl.NumberFormatOptionsFormatting options for the value displayed in the number field. This also affects what characters are allowed to be typed by the user. | |
id | stringId of the element | |
invertWheelChange | booleanWhen | |
locale | stringThe locale to use for formatting and currencies | |
max | numberThe largest value allowed for the input. | |
min | numberThe smallest value allowed for the input. | |
modelValue | number | null | |
name | stringThe name of the field. Submitted with its owning form as part of a name/value pair. | |
readonly | booleanWhen | |
required | booleanWhen | |
step | 1 | numberThe amount that the input value changes with each increment or decrement "tick". |
stepSnapping | true | booleanWhen |
| Event | Payload |
|---|---|
update:modelValue | val: number |
| Slot (default) | Payload |
|---|---|
modelValue | number |
textValue | string |
readonly | boolean |
| Data attribute | Value |
|---|---|
[data-disabled] | Present when disabled |
Input
Input
The input component that renders the text value based on value and format options.
| Prop | Default | Type |
|---|---|---|
as | "input" | AsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. |
| Data attribute | Value |
|---|---|
[data-disabled] | Present when disabled |
Increment
The button that increases the value.
| Prop | Default | Type |
|---|---|---|
as | "button" | AsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. | |
disabled | boolean |
| Data attribute | Value |
|---|---|
[data-pressed] | Present when pressed |
[data-disabled] | Present when disabled |
Decrement
The button that decreases the value.
| Prop | Default | Type |
|---|---|---|
as | "button" | AsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. | |
disabled | boolean |
| Data attribute | Value |
|---|---|
[data-pressed] | Present when pressed |
[data-disabled] | Present when disabled |
Example
Decimal
All options supported by Intl.NumberFormat are supported, including configuration of minimum and maximum fraction digits, sign display, grouping separators, etc.
<template>
<NumberFieldRoot
:default-value="5"
:format-options="{
signDisplay: 'exceptZero',
minimumFractionDigits: 1,
}"
>
…
</NumberFieldRoot>
</template>
Percentage
You can set formatOptions.style to percent to treat the value as a percentage. You need to set the step to 0.01 manually to allow an appropriate step size in this mode.
<template>
<NumberFieldRoot
:default-value="0.05"
:step="0.01"
:format-options="{
style: 'percent',
}"
>
…
</NumberFieldRoot>
</template>
Currency
You can set formatOptions.style to currency to treat the value as a currency value. The currency option must also be passed to set the currency code (e.g., USD).
If you need to allow the user to change the currency, you should include a separate dropdown next to the number field. The number field itself will not determine the currency from the user input.
<template>
<NumberFieldRoot
:default-value="5"
:format-options="{
style: 'currency',
currency: 'EUR',
currencyDisplay: 'code',
currencySign: 'accounting',
}"
>
…
</NumberFieldRoot>
</template>
Accessibility
Adheres to the Spinbutton WAI-ARIA design pattern.
Keyboard Interactions
| Key | Description |
|---|---|
| Arrow Up | Increase the value |
| Arrow Down | Decrease the value |
| Page Up | Increase the value by scale of 10 |
| Page Down | Decrease the value by scale of 10 |
| Home | Set value to minimum (if min is provided) |
| End | Set value to maximum (if max is provided) |