15 KiB
Number Field
A number input that allow users to input custom number entries with a keyboard.
Import
Copyts
import { NumberField } from "@kobalte/core/number-field";
// or
import { Root, Label, ... } from "@kobalte/core/number-field";
// or (deprecated)
import { NumberField } from "@kobalte/core";
Copyts
import { NumberField } from "@kobalte/core/number-field";
// or
import { Root, Label, ... } from "@kobalte/core/number-field";
// or (deprecated)
import { NumberField } from "@kobalte/core";
Features
- Follows the WAI ARIA Spinbutton design pattern.
- Built with a native
<input>element. - Visual and ARIA labeling support.
- Required and invalid states exposed to assistive technology via ARIA.
- Support for description and error message help text linked to the input via ARIA.
- Syncs with form reset events.
- Can be controlled or uncontrolled.
- Supports increment and decrement buttons.
- Format and localize input number and raw input.
- Supports mouse wheel event and all keyboard events.
- Supports browser autofill.
Anatomy
The number field consists of:
- NumberField: The root container for the number field.
- NumberField.Label: The label that gives the user information on the number field.
- NumberField.Input: The native HTML input of the number field, used for display number.
- NumberField.HiddenInput: The native HTML input of the number field, used for raw number form submition.
- NumberField.IncrementTrigger: The increment button of the number field.
- NumberField.DecrementTrigger: The increment button of the number field.
- NumberField.Description: The description that gives the user more information on the number field.
- NumberField.ErrorMessage: The error message that gives the user information about how to fix a validation error on number field.
Copytsx
<NumberField>
<NumberField.Label />
<NumberField.Input />
<NumberField.HiddenInput />
<NumberField.IncrementTrigger />
<NumberField.DecrementTrigger />
<NumberField.Description />
<NumberField.ErrorMessage />
</NumberField>
Copytsx
<NumberField>
<NumberField.Label />
<NumberField.Input />
<NumberField.HiddenInput />
<NumberField.IncrementTrigger />
<NumberField.DecrementTrigger />
<NumberField.Description />
<NumberField.ErrorMessage />
</NumberField>
Example
Quantity
ArrowArrow
index.tsxstyle.css
Copytsx
import { NumberField } from "@kobalte/core/number-field";
import "./style.css";
function App() {
return (
<NumberField class="number-field">
<NumberField.Label class="number-field__label">
Quantity
</NumberField.Label>
<div class="number-field__group">
<NumberField.Input class="number-field__input" />
<NumberField.IncrementTrigger aria-label="Increment" class="number-field__increment"><ArrowUpIcon/></NumberField.IncrementTrigger>
<NumberField.DecrementTrigger aria-label="Decrement" class="number-field__decrement"><ArrowDownIcon/></NumberField.DecrementTrigger>
</div>
</NumberField>
);
}
Copytsx
import { NumberField } from "@kobalte/core/number-field";
import "./style.css";
function App() {
return (
<NumberField class="number-field">
<NumberField.Label class="number-field__label">
Quantity
</NumberField.Label>
<div class="number-field__group">
<NumberField.Input class="number-field__input" />
<NumberField.IncrementTrigger aria-label="Increment" class="number-field__increment"><ArrowUpIcon/></NumberField.IncrementTrigger>
<NumberField.DecrementTrigger aria-label="Decrement" class="number-field__decrement"><ArrowDownIcon/></NumberField.DecrementTrigger>
</div>
</NumberField>
);
}
Usage
Default value
An initial, uncontrolled value can be provided using the defaultValue prop.
Quantity
ArrowArrow
Copytsx
<NumberField defaultValue={40}>
<NumberField.Label>Quantity</NumberField.Label>
<div>
<NumberField.Input />
<NumberField.IncrementTrigger />
<NumberField.DecrementTrigger />
</div>
</NumberField>
Copytsx
<NumberField defaultValue={40}>
<NumberField.Label>Quantity</NumberField.Label>
<div>
<NumberField.Input />
<NumberField.IncrementTrigger />
<NumberField.DecrementTrigger />
</div>
</NumberField>
Controlled value
The value and rawValue props can be used to make the value controlled.
It is recommended to only use the rawValue as it is of type number.
The onChange event is fired when the user type into the input and receive the new value.
The onRawValueChange prop is called when the value changes and receives a number.
Quantity
ArrowArrow
Quantity: 40. Raw: 40.
Copytsx
import { createSignal } from "solid-js";
function ControlledExample() {
const [value, setValue] = createSignal("40");
const [rawValue, setRawValue] = createSignal<number>();
return (
<>
<NumberField
value={value()}
onChange={setValue}
rawValue={rawValue()}
onRawValueChange={setRawValue}
>
<NumberField.Label>Quantity</NumberField.Label>
<div>
<NumberField.Input />
<NumberField.IncrementTrigger />
<NumberField.DecrementTrigger />
</div>
</NumberField>
<p>
Quantity: {value()}. Raw: {rawValue()}.
</p>
</>
);
}
Copytsx
import { createSignal } from "solid-js";
function ControlledExample() {
const [value, setValue] = createSignal("40");
const [rawValue, setRawValue] = createSignal<number>();
return (
<>
<NumberField
value={value()}
onChange={setValue}
rawValue={rawValue()}
onRawValueChange={setRawValue}
>
<NumberField.Label>Quantity</NumberField.Label>
<div>
<NumberField.Input />
<NumberField.IncrementTrigger />
<NumberField.DecrementTrigger />
</div>
</NumberField>
<p>
Quantity: {value()}. Raw: {rawValue()}.
</p>
</>
);
}
Description
The NumberField.Description component can be used to associate additional help text with a number field.
Quantity
ArrowArrow
Choose a quantity.
Copytsx
<NumberField>
<NumberField.Label>Quantity</NumberField.Label>
<div>
<NumberField.Input />
<NumberField.IncrementTrigger />
<NumberField.DecrementTrigger />
</div>
<NumberField.Description>Choose a quantity.</NumberField.Description>
</NumberField>
Copytsx
<NumberField>
<NumberField.Label>Quantity</NumberField.Label>
<div>
<NumberField.Input />
<NumberField.IncrementTrigger />
<NumberField.DecrementTrigger />
</div>
<NumberField.Description>Choose a quantity.</NumberField.Description>
</NumberField>
Error message
The NumberField.ErrorMessage component can be used to help the user fix a validation error. It should be combined with the validationState prop to semantically mark the text field as invalid for assistive technologies.
By default, it will render only when the validationState prop is set to invalid, use the forceMount prop to always render the error message (ex: for usage with animation libraries).
Quantity
ArrowArrow
Hmm, I prefer 40.
Copytsx
import { createSignal } from "solid-js";
function ErrorMessageExample() {
const [rawValue, setRawValue] = createSignal<number>();
return (
<NumberField
onRawValueChange={setRawValue}
validationState={rawValue() !== 40 ? "invalid" : "valid"}
>
<NumberField.Label>Quantity</NumberField.Label>
<div>
<NumberField.Input />
<NumberField.IncrementTrigger />
<NumberField.DecrementTrigger />
</div>
<NumberField.ErrorMessage>Hmm, I prefer 40.</NumberField.ErrorMessage>
</NumberField>
);
}
Copytsx
import { createSignal } from "solid-js";
function ErrorMessageExample() {
const [rawValue, setRawValue] = createSignal<number>();
return (
<NumberField
onRawValueChange={setRawValue}
validationState={rawValue() !== 40 ? "invalid" : "valid"}
>
<NumberField.Label>Quantity</NumberField.Label>
<div>
<NumberField.Input />
<NumberField.IncrementTrigger />
<NumberField.DecrementTrigger />
</div>
<NumberField.ErrorMessage>Hmm, I prefer 40.</NumberField.ErrorMessage>
</NumberField>
);
}
HTML forms
The number field name prop along with <NumberField.HiddenInput/> can be used for integration with HTML forms. Only the raw value is passed to the form.
If the formatted value is wanted (unrecommended) set the name attribute on <NumberField.Input/>.
Quantity
ArrowArrow
ResetSubmit
Copytsx
function HTMLFormExample() {
const onSubmit = (e: SubmitEvent) => {
// handle form submission.
};
return (
<form onSubmit={onSubmit}>
<NumberField name="quantity">
<NumberField.Label>Quantity</NumberField.Label>
<NumberField.HiddenInput />
<div>
<NumberField.Input />
<NumberField.IncrementTrigger />
<NumberField.DecrementTrigger />
</div>
</NumberField>
<div>
<button type="reset">Reset</button>
<button type="submit">Submit</button>
</div>
</form>
);
}
Copytsx
function HTMLFormExample() {
const onSubmit = (e: SubmitEvent) => {
// handle form submission.
};
return (
<form onSubmit={onSubmit}>
<NumberField name="quantity">
<NumberField.Label>Quantity</NumberField.Label>
<NumberField.HiddenInput />
<div>
<NumberField.Input />
<NumberField.IncrementTrigger />
<NumberField.DecrementTrigger />
</div>
</NumberField>
<div>
<button type="reset">Reset</button>
<button type="submit">Submit</button>
</div>
</form>
);
}
Triggers
The number field supports optional increment/decrement triggers that are easily customizable.
Quantity
-+
Copytsx
<NumberField>
<NumberField.Label>Quantity</NumberField.Label>
<div>
<NumberField.DecrementTrigger class="custom-trigger">-</NumberField.DecrementTrigger>
<NumberField.Input />
<NumberField.IncrementTrigger class="custom-trigger">+</NumberField.IncrementTrigger>
</div>
</NumberField>
Copytsx
<NumberField>
<NumberField.Label>Quantity</NumberField.Label>
<div>
<NumberField.DecrementTrigger class="custom-trigger">-</NumberField.DecrementTrigger>
<NumberField.Input />
<NumberField.IncrementTrigger class="custom-trigger">+</NumberField.IncrementTrigger>
</div>
</NumberField>
Format
The value of the number field component can be formatted based on the locale with the I18NProvider and formatOptions. For more information see React Spectrum NumberField.
Price
ArrowArrow
Copytsx
<NumberField formatOptions={{ style: "currency", currency: "USD" }} defaultValue={4}>
<NumberField.Label>Price</NumberField.Label>
<div>
<NumberField.Input />
<NumberField.IncrementTrigger />
<NumberField.DecrementTrigger />
</div>
</NumberField>
Copytsx
<NumberField formatOptions={{ style: "currency", currency: "USD" }} defaultValue={4}>
<NumberField.Label>Price</NumberField.Label>
<div>
<NumberField.Input />
<NumberField.IncrementTrigger />
<NumberField.DecrementTrigger />
</div>
</NumberField>
Autofill
The number field supports autofill through NumberField.HiddenInput.
Copytsx
<NumberField>
<NumberField.Label>Quantity</NumberField.Label>
<NumberField.HiddenInput />
<div>
<NumberField.Input />
<NumberField.IncrementTrigger />
<NumberField.DecrementTrigger />
</div>
</NumberField>
Copytsx
<NumberField>
<NumberField.Label>Quantity</NumberField.Label>
<NumberField.HiddenInput />
<div>
<NumberField.Input />
<NumberField.IncrementTrigger />
<NumberField.DecrementTrigger />
</div>
</NumberField>
API Reference
NumberField
NumberField is equivalent to the Root import from @kobalte/core/number-field (and deprecated NumberField.Root).
| Prop | Description |
|---|---|
| value | `string |
| defaultValue | `string |
| onChange | (value: string) => voidEvent handler called when the value of the NumberField changes as a formatted value. |
| rawValue | numberThe controlled raw value of the number field. |
| onRawValueChange | (value: number) => voidEvent handler called when the value of the NumberField changes as a number. |
| minValue | numberThe smallest value allowed in the number field, defaults to Number.MIN_SAFE_INTEGER. |
| maxValue | numberThe largest value allowed in the number field, defaults to Number.MAX_SAFE_INTEGER. |
| step | numberIncrement/Decrement step when using the triggers or the arrows on keyboard in the number field. |
| largeStep | numberIncrement/Decrement step when using the Page UP/Down keys in the number field, defaults 10 * step. |
| changeOnWheel | booleanWhether to increment/decrement on wheel scroll inside the number field. |
| format | booleanWhether to format the input value. |
| formatOptions | Intl.NumberFormatOptionsFormating options for the value of the number field. |
| allowedInput | RegExpAllowed input characters in the number field (only prevents onInput, not paste), defaults to locale and format characters. |
| name | stringThe name of the NumberField.HiddenInput of the number field, used when submitting an HTML form. See MDN. |
| validationState | `'valid' |
| required | booleanWhether the user must fill the number field before the owning form can be submitted. |
| disabled | booleanWhether the number field is disabled. |
| readOnly | booleanWhether the number field items can be selected but not changed by the user. |
| Data attribute | Description |
|---|---|
| data-valid | Present when the number field is valid according to the validation rules. |
| data-invalid | Present when the number field is invalid according to the validation rules. |
| data-required | Present when the user must fill the number field before the owning form can be submitted. |
| data-disabled | Present when the number field is disabled. |
| data-readonly | Present when the number field is read only. |
NumberField.Label, NumberField.Input, NumberField.HiddenInput, NumberField.Description and NumberField.ErrorMesssage share the same data-attributes.
NumberField.ErrorMessage
| Prop | Description |
|---|---|
| forceMount | booleanUsed to force mounting when more control is needed. Useful when controlling animation with SolidJS animation libraries. |
Rendered elements
| Component | Default rendered element |
|---|---|
NumberField |
div |
NumberField.Label |
label |
NumberField.Input |
input |
NumberField.HiddenInput |
input |
NumberField.IncrementTrigger |
button |
NumberField.DecrementTrigger |
button |
NumberField.Description |
div |
NumberField.ErrorMessage |
div |
Previous←Navigation MenuNextPagination→