XDSNumberInput@xds/core · NumberInput
Preview coming soon
Usage
A form input for numeric values with built-in validation, min/max constraints, and step controls. Use NumberInput for quantities, measurements, percentages, and similar inputs.Best practices
| Guidance | Practices |
|---|---|
| Do | Set min, max, and step to guide users toward valid values. |
| Do | Show units (e.g. "%" or "GB") so users know what the number represents. |
| Don't | Use NumberInput for free-form text that happens to contain numbers — use TextInput instead. |
| Don't | Set both isOptional and isRequired on the same field. |
Anatomy
| Element | Description | |
|---|---|---|
| Label | required | The label for the number input. |
| Description | Additional description text below the label. | |
| Icon | An optional icon within the input. | |
| Placeholder | Placeholder text shown when the input is empty. | |
| Spinner | Increment and decrement controls for the value. |
Import
tsimport {XDSNumberInput} from '@xds/core/NumberInput'
Props
| Prop | Type | Description |
|---|---|---|
labelrequired | string | Label text for the input (always rendered for accessibility). |
valuerequired | number | null | undefined | Current value of the input. |
onChangerequired | (value: number) => void | Callback fired when input value changes (only on valid input). |
size | 'sm' | 'md' | 'lg' (default: 'md') | Size variant. |
isLabelHidden | boolean | Visually hide the label (still accessible to screen readers). |
description | string | Description text displayed between the label and input. |
isOptional | boolean | Whether the field is optional (mutually exclusive with isRequired). |
isRequired | boolean | Whether the field is required (mutually exclusive with isOptional). |
isDisabled | boolean | Whether the input is disabled. |
placeholder | string | Placeholder text. |
labelTooltip | string | Tooltip text to display in an info icon at the end of the label. |
startIcon | XDSIconType | Icon to display at the start of the input. See `npx xds docs icons` for valid semantic names. |
labelIcon | XDSIconType | Icon to display before the label text. See `npx xds docs icons` for valid semantic names. |
status | {type: 'error' | 'warning' | 'success', message?: string} | Validation status with optional message. |
min | number | null | Minimum value allowed. |
max | number | null | Maximum value allowed. |
step | number | null (default: 1) | Step increment for the input. |
units | string | null | Units text to display at the end of the input (e.g., "%" or "GB"). |
isIntegerOnly | boolean | Only allow integer values (no floating point). |
hasClear | boolean (default: false) | Shows a clear (×) button when the input has a value. When true, the onChange callback also accepts null to signal the user cleared the input. |
htmlName | string | HTML name attribute for form submissions. |
autoComplete | string | HTML autocomplete attribute. |
hasAutoFocus | boolean | Whether to focus the input on mount. |
onFocus | (e: FocusEvent<HTMLInputElement>) => void | Callback fired when the input receives focus. |
onBlur | (e: FocusEvent<HTMLInputElement>) => void | Callback fired when the input loses focus. |
onEnter | () => void | Callback fired when the user presses the Enter key. |
Examples
Common configurations, variations, and states.NumberInput — ClearableNumber input with a clear button, unit suffix, and min/max constraint
tsx'use client';import {useState} from 'react';import {XDSNumberInput} from '@xds/core/NumberInput';import {XDSCenter} from '@xds/core/Center';export default function NumberInputClearableNumberInput() {const [value, setValue] = useState<number | null>(75);return (<XDSCenter width={300}><XDSNumberInputlabel="Progress"units="%"min={0}max={100}value={value}onChange={setValue}hasClear/></XDSCenter>);}
NumberInput — Range ConstrainedNumber input with min/max boundaries and a helper description
tsx'use client';import {useState} from 'react';import {XDSNumberInput} from '@xds/core/NumberInput';import {XDSCenter} from '@xds/core/Center';export default function NumberInputRangeNumberInput() {const [value, setValue] = useState<number | null>(3);return (<XDSCenter width={300}><XDSNumberInputlabel="Team Size"placeholder="1–50"min={1}max={50}description="Number of people on the team"value={value}onChange={setValue}/></XDSCenter>);}
NumberInput — Status VariantsNumber inputs showing error, warning, and success validation states
tsx'use client';import {useState} from 'react';import {XDSNumberInput} from '@xds/core/NumberInput';import {XDSVStack} from '@xds/core/Stack';import {XDSCenter} from '@xds/core/Center';export default function NumberInputStatuses() {const [error, setError] = useState<number | null>(-5);const [warning, setWarning] = useState<number | null>(150);const [success, setSuccess] = useState<number | null>(25);return (<XDSCenter width={300}><XDSVStack gap={4}><XDSNumberInputlabel="Budget"value={error}onChange={setError}status={{type: 'error', message: 'Must be a positive amount'}}/><XDSNumberInputlabel="Headcount"value={warning}onChange={setWarning}status={{type: 'warning', message: 'Exceeds typical team size'}}/><XDSNumberInputlabel="Completion"units="%"value={success}onChange={setSuccess}status={{type: 'success', message: 'On track'}}/></XDSVStack></XDSCenter>);}
NumberInput — With UnitsNumber input with a percentage unit suffix and valid range
tsx'use client';import {useState} from 'react';import {XDSNumberInput} from '@xds/core/NumberInput';import {XDSCenter} from '@xds/core/Center';export default function NumberInputWithUnits() {const [value, setValue] = useState<number | null>(50);return (<XDSCenter width={300}><XDSNumberInputlabel="Discount"placeholder="Enter discount"min={0}max={100}units="%"value={value}onChange={setValue}/></XDSCenter>);}
Showcase source
tsximport {XDSNumberInput} from '@xds/core/NumberInput';export default function NumberInputShowcase() {return (<div style={{maxWidth: 300}}><XDSNumberInputlabel="Quantity"placeholder="Enter quantity"value={0}onChange={() => {}}/></div>);}