NumberField
A small field for an exact number, with arrow-key steps, a stepper on hover and scrubbing by dragging its label.
import { NumberField } from "@butteryui/react";Demo
When to use it
Use it for
- Exact sizes and positions: width, height, x, y, a crop in pixels
- Pairs of numbers in an inspector or a menu footer
- A dense panel, with size="sm"; a field on a white card or in a toolbar, with variant="soft"
Not for
- A value judged by eye: use Slider
- Free text or long numbers such as phone numbers: use a text input
Examples
Crop size
A crop's width and height in pixels, side by side, each kept in state with the size it makes.
Crops to 1200 × 630 px
Export size
An export panel: width and height fields with their labels on top, each filling its column, and the button that uses them.
Not exported yet
Scale factor
A scale factor in tenths, from 0.1 to 4, saved once each change is final rather than on every keystroke.
No changes yet
Sizes and soft
A batch's weights in small soft fields for a dense panel, and its price in a large one beside large fields.
17% lost in the roast
Variants and states
Width and height
Type and press Enter, use the arrow keys (Shift for ten), hover for the stepper, or drag the W and H labels sideways.
Label on top
Each field fills its column under its label, as in a menu's width and height fields.
Decimals and disabled
Sizes, outline and soft
28, 34 and 48px tall, 16px digits at lg; soft sits on bg-control and shows its edge only on hover and while it has focus.
Props
NumberField
| Prop | Type | Default | Description |
|---|---|---|---|
labelrequired | string | What the number is, shown before the field. Drag it sideways to scrub the value. | |
value | number | The value. Pair with onValueChange to control it. | |
defaultValue | number | min | The starting value when uncontrolled. Defaults to min, or 0. |
onValueChange | ((value: number) => void) | Called with each committed value: on Enter, on leaving the field, on a step and while scrubbing. | |
onValueCommit | ((value: number) => void) | Called once a change is final: on Enter, on leaving the field, on a step, and when a scrub ends, for an undo step per change rather than per scrubbed frame. | |
min | number | The lowest value. | |
max | number | The highest value. | |
step | number | 1 | The smallest change. Arrow keys and the stepper move one step, Shift ten. Defaults to 1. |
unit | string | A unit shown after the number, such as "px". | |
labelPosition | "side" | "top" | "side" | Where the label sits: "side" (the default), before a 128px field, or "top", above a field that
fills its column, as in a pair of width and height fields. |
size | "sm" | "md" | "lg" | "md" | The field's height: "md" (34px, 30 compact, the default), "sm" (28px) for a dense panel, or "lg" (48px,
40 compact, with 16px digits) beside large fields. |
variant | "outline" | "soft" | "outline" | "outline" (the default), a 1px control-border edge on bg-surface, or "soft", a bg-control fill whose
edge shows only on hover and while it has focus. |
It also takes Omit<ComponentPropsWithRef<"input">, "value" | "defaultValue" | "onChange" | "type" | "min" | "max" | "step" | "size" | "children">.
Accessibility
A spinbutton named by its label: arrow keys step, Shift and an arrow steps ten, Enter or leaving commits what was typed, Escape puts back the last value. The stepper buttons skip the tab order, since the arrow keys do the same.
| Keys | What they do |
|---|---|
| Up or Down arrow | Raises or lowers the value by one step |
| Shift and an arrow | Moves it ten steps at a time |
| Enter | Commits what was typed |
| Escape | Puts back the last value, dropping what was typed |
| Tab | Commits what was typed and moves on, past the stepper's buttons |
Motion
It doesn't move.
With reduced motion: Nothing changes.
Layout
With labelPosition="side", the default, the label sits before a 128px field; with "top" it sits above a field that fills its column. The field is 34px tall (--bt-h-control, 30 compact), 28px (--bt-h-sm) at size="sm" or 48px (--bt-h-cta, 40 compact) with 16px digits at "lg", and its number uses tabular figures; a long label truncates with an ellipsis and shows in full as its title. The stepper's 24px buttons show on hover and focus, and a field narrower than 112px drops them, keeping the arrow keys and the label's scrub.