NumberInput
Units and validation
Arrow keys step by 10 m. Home and End select the bounds.
Clear the field to mark the value unknown.
Unknown
Unknown
Enter a value of at least 0 m.
const [altitude, setAltitude] = useState<number | null>(1200);
const [error, setError] = useState<string | null>(null);
<NumberInput
label="Altitude"
unit="m"
value={altitude}
onValueChange={setAltitude}
onValidationChange={setError}
min={0}
max={20000}
step={10}
/>;
// Disable application submission while error !== null.
The unit is required and remains separate from the numeric text, beside it. A long unit
wraps in its own column and the field grows taller, while the number keeps about ten
characters of room; a one-line field keeps its exact height. There is no unit
conversion. Empty text represents null (unknown), rather than zero; use required
to make unknown values invalid. defaultValue initializes an uncontrolled field.
Decimal text, signs, and scientific notation are accepted. Invalid drafts remain visible
with an associated message and never emit NaN, infinity, out-of-range values, or an
invalid step. onValueChange therefore retains the last valid committed value while the
field is invalid. Use onValidationChange when implementing application-level submission,
or native form constraint validation when using name inside a form.
Numeric step validates from min, or from zero when min is omitted. The default "any"
allows decimal values and uses increments of 1 for keyboard stepping. error displays
caller validation ahead of built-in validation, and is announced as an alert; the
field's own as-you-type message stays a quiet description. readOnly retains focus
without edits; disabled removes the field from interaction and shows it as unavailable
(dim text on a muted fill, with the control outline), its value still readable.
Props
| PROP | TYPE | DEFAULT | REQUIRED |
|---|---|---|---|
label | string | — | yes |
unitVisible and described unit such as m, kn or °. Empty units are invalid; no conversion is performed. | string | — | yes |
valueControlled number or null for unknown. Invalid drafts stay visible and never emit NaN or out-of-range values. | number | — | no |
defaultValueInitial uncontrolled number, or null (the default). | number | — | no |
onValueChange(value: number | null) => void. Emits valid numeric edits or null when cleared. Does not emit invalid drafts. | function | — | no |
onValidationChange(error: string | null) => void. Reports draft and supplied-value validation; use this to block application submission while a draft is invalid. | function | — | no |
min | number | — | no |
max | number | — | no |
stepPositive number or 'any'. Numeric steps validate from min (or zero); Arrow keys use 1 for 'any'. | string | "any" | no |
size | enumsm | md | lg | "md" | no |
disabled | boolean | false | no |
readOnly | boolean | false | no |
required | boolean | false | no |
description | string | — | no |
errorCaller-supplied validation error, displayed before built-in validation. | string | — | no |
nameNative form field name. Constraint validation blocks invalid numeric drafts. | string | — | no |
Accessibility
- The visible label names a spinbutton; the unit and validation message are associated descriptions.
- The label keeps the case it is written in; the label, description and message wrap, and long identifiers break anywhere.
aria-valuenowis a plain decimal, even when the field shows a value in exponent form.- The field outline is the control outline (
--oprt-border-control, 3:1 or more). - NumberInput carries its own label; do not place it in a Field.
- Arrow Up/Down step within the bounds. Home/End use
min/maxwhen supplied. - Unknown and invalid states are written explicitly and never conveyed by color alone.
- Numeric text uses OPERATOR Mono; label and feedback use OPERATOR Sans. Focus is visible around the control.
Manifest entry
<NumberInput label="Altitude" unit="m" value={altitude} onValueChange={setAltitude} min={0} max={20000} step={10} />View agent manifest
{
"description": "Numeric entry with an explicit unit, keyboard stepping, range and step validation, and unknown-value state.",
"props": {
"label": {
"type": "string",
"required": true
},
"unit": {
"type": "string",
"required": true,
"description": "Visible and described unit such as m, kn or °. Empty units are invalid; no conversion is performed."
},
"value": {
"type": "number",
"description": "Controlled number or null for unknown. Invalid drafts stay visible and never emit NaN or out-of-range values."
},
"defaultValue": {
"type": "number",
"description": "Initial uncontrolled number, or null (the default)."
},
"onValueChange": {
"type": "function",
"description": "(value: number | null) => void. Emits valid numeric edits or null when cleared. Does not emit invalid drafts."
},
"onValidationChange": {
"type": "function",
"description": "(error: string | null) => void. Reports draft and supplied-value validation; use this to block application submission while a draft is invalid."
},
"min": {
"type": "number"
},
"max": {
"type": "number"
},
"step": {
"type": "string",
"default": "any",
"description": "Positive number or 'any'. Numeric steps validate from min (or zero); Arrow keys use 1 for 'any'."
},
"size": {
"type": "enum",
"values": [
"sm",
"md",
"lg"
],
"default": "md"
},
"disabled": {
"type": "boolean",
"default": false
},
"readOnly": {
"type": "boolean",
"default": false
},
"required": {
"type": "boolean",
"default": false
},
"description": {
"type": "string"
},
"error": {
"type": "string",
"description": "Caller-supplied validation error, displayed before built-in validation."
},
"name": {
"type": "string",
"description": "Native form field name. Constraint validation blocks invalid numeric drafts."
}
},
"composable_with": [
"Card",
"CoordinateInput"
],
"never_inside": [
"Button"
],
"example": "<NumberInput label=\"Altitude\" unit=\"m\" value={altitude} onValueChange={setAltitude} min={0} max={20000} step={10} />"
}