NumberField
StableA number box with minus and plus buttons, keyboard stepping, limits and an optional unit.
Also known as number input, numeric input, stepper input, spin button
Install with npm install @tattva/ui (setup), or copy the code from the kit in Downloads.
Quantity with limits
function Example() {
const [n, setN] = useState<number | null>(2);
return <NumberField label="Lots" value={n} onChange={setN} min={1} max={50} unit="lots" />;
}The buttons stop at 1 and 50. Type a number and press Enter or leave the box to apply it.
When to use it
A number the user may know exactly (type it) or want to nudge (step it), such as a quantity or a price, with limits that are enforced for them.
Made of: Decrease button · Number · Unit · Increase button
Use it for
- A quantity, count or size with a minimum and maximum.
- A price or other decimal value with a fixed number of places.
- A value with a unit shown after it.
Not for
- Digits that are not a quantity, like a phone number or a code: use TextField.
- A choice between a few named options: use SegmentedControl.
- Picking from a list of named values: use Select.
Do and avoid
Do
- Set min and max when the number has real limits.
- Set precision for money or other fixed decimals.
- Use unit instead of putting the unit in the label alone.
- Say the limits in a hint, so people know them before they hit one.
Avoid
- Do not use it for phone numbers, codes or ids. Use TextField.
- Do not use it for a huge range where stepping is useless.
- Do not expect onChange on every key press. Typing is applied on blur and Enter.
- Do not rely on the buttons alone. The buttons are skipped by the Tab key, because the arrow keys do the same job.
On a phone
- The box is 44px tall and the minus and plus buttons are at least 44px wide on touch screens.
- Typing opens the decimal keypad when the minimum is 0 or more, and otherwise the normal keyboard, and the value is checked on Enter or when the field loses focus, so tell users to tap away to confirm.
- When the minimum is below 0 the field uses the normal keyboard so a minus can be typed; the minus and plus buttons work either way.
Properties
| Prop | Type | Default | Description |
|---|---|---|---|
| valuerequired | number | null | none | Current value. null shows an empty box. The component is controlled. |
| onChangerequired | (value: number | null) => void | none | Called with the new value after a step, or after typing is applied on blur or Enter. Called with null if the box was cleared. |
| labelrequired | string | none | Accessible name of the input, also used in the button names (Decrease and Increase). |
| min | number | none | Lowest allowed value. Also the target of the Home key. |
| max | number | none | Highest allowed value. Also the target of the End key. |
| step | number | 1 | Amount for the buttons and Arrow keys. Shift with an arrow, Page Up and Page Down move ten steps. |
| precision | number | none | Decimals shown and kept. Defaults to the decimals in step. |
| unit | string | none | Text shown after the number. It is added to the spoken value. |
| invalid | boolean | none | Danger border and aria-invalid. |
| disabled | boolean | none | Dims the box and disables the input and buttons. |
| size | "sm" | "md" | "md" | md is 40px tall, sm is 32px. Both are 44px on coarse pointers. |
| id | string | none | Id on the input, for a label that uses htmlFor. Field passes this. |
| aria-describedby | string | none | Ids of hint or error text. Field passes this. |
| aria-invalid | boolean | none | Same effect as invalid. Field passes this when it has an error. |
| required | boolean | none | Sets required on the input. |
| className | string | none | Classes for the outer box. |
"Show code under the preview gives the code for the example on the stage."
In Figma
In Figma, one NumberField switches all of this from its properties panel, across 8 variants. Each property sets the React prop beside it, so design and code use the same names.
| Figma property | React | Values |
|---|---|---|
| Invalid | invalid | On or off |
| Size | size | SM, MD |
| Disabled | disabled | On or off |
| Unit | unit | Any text |
States
States this part has beyond its default look. Build each one your screen can reach. States set by a property are in the Code tab.
- hover
- The border gets stronger when the pointer is over the box, and a step button shades when the pointer is over it.
- focus
- A focus ring is drawn around the whole box when the number is focused with the keyboard.
- at limit
- The Decrease button is disabled at min and the Increase button at max.
- editing
- While you type, the text is kept as typed. It is checked, clamped and rounded when you leave the field or press Enter.
- empty
- A value of null shows an empty box. Arrow keys and the buttons then start from min, or 0 if there is no min.
Tokens
Change one of these and every part that uses it follows.
--border--border-strong--danger--surface--surface-hover--fg--fg-muted--focus-ring--dur-fast--radius-field
Built in
- The input has the spinbutton role with aria-valuenow, aria-valuemin and aria-valuemax, as the WAI-ARIA pattern asks.
- aria-valuetext adds the unit to the spoken value.
- Arrow Up and Down change the value by one step. Shift with an arrow, Page Up and Page Down change it by ten steps. Home and End jump to min and max when they are set.
- The buttons are named Decrease and Increase with the label, and are disabled at the limits.
- The buttons are skipped by the Tab key so the field is one stop. They are still pressable with mouse and touch.
- The input is a text input with a decimal keyboard on phones.
- Numbers use tabular figures so digits line up.
- The step buttons are 44px wide on coarse pointers.
What you need to do
- Pass label. It is the accessible name, and the step buttons are named from it, for example "Decrease Lots".
- Inside Field, pass the same text as label and spread the wiring props so the hint and error are read.
- Tell people the limits in a hint, since min and max only clamp the value.
Built toward WCAG 2.2 AA and checked automatically; no independent audit yet. Read the accessibility guide