NumberField
number-fieldEdits numeric values with bounds, step buttons, and keyboard stepping.
Usage
Basic usage
±Button stepping, the input box can be typed directly, and the keyboard is supported ↑↓.
tsx
<NumberField aria-label="Quantity" defaultValue={3} />Scope Limitation
min/max constraint value, the corresponding button is automatically disabled when the boundary is reached.
tsx
<NumberField aria-label="Quantity" defaultValue={0} min={0} max={5} />Step size
step Set the amount of each increase or decrease, here each step is 5.
tsx
<NumberField aria-label="Step size 5" defaultValue={10} step={5} />Disabled
disabled Locks the entire control.
tsx
<NumberField aria-label="Quantity" defaultValue={3} disabled />When to use
Use NumberField for precise numeric input with increment/decrement buttons and min/max bounds, such as quantities or thresholds. Use Slider for approximate values selected by dragging, or Input for arbitrary text.
Import
ts
import { NumberField } from "@hulianui/ui"Props
| Name | Type | Default | Description |
|---|---|---|---|
| value | number|null | - | Controlled value; null represents empty. |
| defaultValue | number|null | - | Initial value when uncontrolled; null starts empty, matching value. |
| min | number | - | Minimum value. |
| max | number | - | Maximum value. |
| step | number | 1 | Increment or decrement amount. |
| disabled | boolean | false | Disables interaction. |
| readOnly | boolean | false | Makes the field read-only. |
| required | boolean | - | Marks the native form field as required. |
| name | string | - | Native form name |
| id | string | - | - |
| className | string | - | - |
| aria-label | string | - | Provided when no title is visible |
Events
| Event | Type | Description |
|---|---|---|
| onValueChange | (value: number|null) => void | Called with the new value. HulianUI intentionally omits Base UI's eventDetails. |
Example
tsx
<NumberField aria-label="Quantity" defaultValue={3} min={0} max={5} />Controlled (value can be null):
tsx
const [v, setV] = useState<number | null>(2);
<NumberField aria-label="Quantity" value={v} onValueChange={setV} min={0} max={10} />Usage guidelines
- The controlled type is
number | null: clearing emitsnull, so use state such asuseState<number | null>instead of assuming a number is always present. The reverse direction holds too: passingnullintovalue(ordefaultValue) renders an empty string with the placeholder visible rather than0, andmin={0}does not clamp it to 0. Tri-state fields (null/0/ a positive number) such as "leave empty to inherit the default" versus "explicitly zero" can therefore be expressed with this component, and the two stay distinguishable on screen. - Controlled usage requires both
valueandonValueChange. For uncontrolled usage, provide onlydefaultValue. - Values outside the signature are treated as empty rather than falling to `0` (#220).
valueonly acceptsnumber | null, yet controlled values often arrive through type-erased paths (register().valuefromuseFormisunknown, an API payload isany), so an empty string can slip in - and the underlying control renders that as0, the worst possible landing spot for a tri-state field ("left blank" and "explicitly zero" are opposite business conclusions that then look identical on screen). Such values are now treated as empty, with onewarnOncein development naming the source.undefinedis excluded: that means uncontrolled and is passed through untouched. - Provide
aria-labelwhen there is no visible label so screen readers can identify the field.
Related
Input · Textarea · Select · Checkbox · CheckboxGroup · Radio
Playground
<NumberField defaultValue={3} />