import { Field, FieldLabel } from "@hel/ui/field"
import {
NumberField,When to use it#
Use a number field when the answer is a number and small steps make sense: a quantity, a number of guests, a percentage. People can type the number, press the buttons, use the arrow keys or scroll.
If the number is money or has a fixed shape, such as a price or a phone number, use the Masked Inputs instead. If the choice is a position along a range, a Slider fits better.
Import#
import {
NumberField,
NumberFieldGroup,
NumberFieldInput,
NumberFieldIncrement,
NumberFieldDecrement,
NumberFieldScrubArea,
NumberFieldScrubAreaCursor,
} from "@hel/ui/number-field"Anatomy#
NumberField holds the value and the rules. Inside it, NumberFieldGroup draws one bordered box around the decrement button, the input and the increment button. You can leave the buttons out for a plain number input.
<NumberField defaultValue={2} min={1}>
<NumberFieldGroup>
<NumberFieldDecrement />
<NumberFieldInput />
<NumberFieldIncrement />
</NumberFieldGroup>
</NumberField>Put it in a Field to give it a label and a description. An invalid field turns the border red.
Examples#
Range and step#
min and max limit the value, and the button at the limit is disabled. step is how far one press moves. largeStep is used while Shift is held, and smallStep while Alt is held.
Tables seat 1 to 12 people.
Boxes of 6. Hold Shift for 10 boxes.
import {
Field,
FieldDescription,Formats#
Pass currency for money. The symbol and decimals follow the app's config, the same way the Money component shows them. For anything else, format takes any Intl.NumberFormatOptions, such as a percent or a unit. When both are given, format wins.
A percent counts in fractions, so 0.15 is 15%. Set step to match.
import { Field, FieldLabel } from "@hel/ui/field"
import {
NumberField,Scrub label#
Wrap a label in NumberFieldScrubArea and the person can drag it sideways to change the value, the way design tools work. A custom cursor appears while dragging. Give the field an id and point the label at it with htmlFor. Set direction="vertical" on the scrub area to drag up and down instead.
import * as React from "react"
import { Label } from "@hel/ui/label"Controlled value#
The value is a number, or null when the input is empty. Handle null before you do math with it.
Total: $54
import * as React from "react"
import { Field, FieldLabel } from "@hel/ui/field"Sizes#
size is sm, md or lg, and it is set once on NumberField for the group, the input and both buttons. The default is md. The sizes match the heights of the other controls, so a number field lines up with buttons and inputs next to it.
States#
disabled and readOnly apply to the whole field. required marks the number as needed. allowWheelScrub lets the mouse wheel change the value while the input is focused, which is off by default so scrolling the page does not change a number by accident.
Props#
NumberField#
| Prop | Type | Default |
|---|---|---|
value / defaultValue | number | null | none |
onValueChange | (value: number | null) => void | none |
min / max | number | none |
step | number | 1 |
smallStep / largeStep | number | 0.1 / 10 |
format | Intl.NumberFormatOptions | plain number |
currency | string (ISO 4217) | none |
locale | string | The browser locale |
size | "sm" | "md" | "lg" | "md" |
allowWheelScrub | boolean | false |
disabled / readOnly / required | boolean | false |
name | string | none |
It also takes every prop of the Base UI number field.
The other parts#
| Part | What it is |
|---|---|
NumberFieldGroup | The bordered box around the buttons and the input. |
NumberFieldInput | The text input. |
NumberFieldIncrement / NumberFieldDecrement | The plus and minus buttons. |
NumberFieldScrubArea | A draggable area, usually around the label. Takes direction. |
NumberFieldScrubAreaCursor | The cursor shown while dragging. Put it inside the scrub area. |