Number Input
The number input component provides a structured way for users to input numerical data with built-in validation and controls. It combines a text input field with stepper buttons and can include unit selection functionality for measurements, currency, or other quantifiable values.
import {NumberInput} from "@qualcomm-ui/react/number-input"Examples
Simple
The simple API bundles all subcomponents together into a single component.
<NumberInput className="w-72" label="Label" placeholder="Enter a number" />
Composite
The composite pattern provides full control over the component's elements by composing individual subcomponents.
<NumberInput.Root className="w-72">
<NumberInput.Label>Label</NumberInput.Label>
<NumberInput.InputGroup>
<NumberInput.Input placeholder="Enter a number" />
<NumberInput.Control />
<NumberInput.ErrorIndicator />
</NumberInput.InputGroup>
<NumberInput.Hint>Optional hint</NumberInput.Hint>
</NumberInput.Root>
Min and Max values
Pass the min and max props to the root component to set the minimum and maximum values of the number input.
If the value entered is less than min or greater than max, it will be clamped to the nearest boundary on blur or enter.
<NumberInput
aria-label="input min-max demo"
className="w-72"
defaultValue="5"
max={10}
min={5}
/>
Step interval
Pass the step prop to the root component to set the increment or decrement step interval.
<NumberInput
aria-label="Steps demo"
className="w-72"
placeholder="Enter a number"
step={3}
/>
States
The following shows how the NumberInput component appears in each interactive state.
<NumberInput disabled label="Disabled" placeholder="Disabled" />
<NumberInput label="Read only" placeholder="Read only" readOnly />
<NumberInput label="Required" placeholder="Required" required />
<NumberInput
errorText="Invalid"
invalid
label="Invalid"
placeholder="Invalid"
/>
Controlled Value
Use the value, onValueChange and defaultValue props to control the value of the input field. These props follow our controlled state pattern.
import {type ReactElement, useState} from "react"
import {NumberInput} from "@qualcomm-ui/react/number-input"
export function NumberInputControlledDemo(): ReactElement {
const [value, setValue] = useState<string>("")
return (
<NumberInput
className="w-72"
label="Controlled Value"
onValueChange={({value}) => setValue(value)}
placeholder="Placeholder"
value={value}
/>
)
}Sizes
Customize size using the size prop. The default size is md.
<NumberInput
aria-label="sm demo"
className="w-56"
placeholder="sm"
size="sm"
startIcon={Sigma}
/>
<NumberInput
aria-label="md demo"
className="w-64"
placeholder="md"
startIcon={Sigma}
/>
<NumberInput
aria-label="lg demo"
className="w-72"
placeholder="lg"
size="lg"
startIcon={Sigma}
/>
Unit Selector
Add a unit selector to the number input by passing an array of options to the unitOptions prop.
The selected unit follows our controlled state pattern: use defaultUnit for uncontrolled state, or unit with onUnitChange for controlled state.
<NumberInput
className="w-72"
defaultUnit="USD"
label="Price"
placeholder="0.00"
unitOptions={currencyOptions}
value="0"
/>
Error Text and Indicator
Error messages are displayed using two props:
The error text and indicator will only render when invalid is true.
<NumberInput
className="w-72"
errorText="You must enter a value"
invalid={!value}
label="Label"
onValueChange={({value}) => setValue(value)}
placeholder="Enter a value"
value={value}
/>
Explorer
Component Anatomy
Hover to highlight, click to view API
API
<NumberInput>
The NumberInput component supports all props from NumberInput.Root, plus the additional props listed below.
{
children?: ReactNode
render?:
| Element
| ((
props: Props,
) => Element)
}
{
render?:
| Element
| ((
props: Props,
) => Element)
}
{
icon?:
| LucideIcon
| ReactNode
render?:
| Element
| ((
props: Props,
) => Element)
}
{
id?: string
render?:
| Element
| ((
props: Props,
) => Element)
}
{
render?:
| Element
| ((
props: Props,
) => Element)
}
{
render?:
| Element
| ((
props: Props,
) => Element)
}
any{
children?: ReactNode
id?: string
required?: boolean
}
string{id?: string}
Composite API
<NumberInput.Root>
booleanbooleanbooleanstringstring'ltr' | 'rtl'
booleanbooleanstringNumberFormatOptionsIntl.NumberFormat constructor() =>
| Node
| ShadowRoot
| Document
Partial<{
decrementTrigger: string
errorText: string
hint: string
incrementTrigger: string
input: string
label: string
}>
| 'text'
| 'tel'
| 'numeric'
| 'decimal'
booleanstringnumbernumberstring(
details: NumberInputFocusChangeDetails,
) => void
(
unit: string,
) => void
(
details: NumberInputValueChangeDetails,
) => void
(
details: NumberInputValueInvalidDetails,
) => void
stringboolean| ReactElement
| ((
props: object,
) => ReactElement)
boolean| 'sm'
| 'md'
| 'lg'
boolean| LucideIcon
| ReactNode
number{
decrementLabel?: string
incrementLabel?: string
valueText?: (
value: string,
) => string
}
stringArray<{
displayText?: string
label: string
value: string
}>
stringdata-disableddata-focusdata-invaliddata-number-input-part'root'<NumberInput.Label>
data-disableddata-focusdata-invaliddata-number-input-part'label'<NumberInput.InputGroup>
| ReactElement
| ((
props: object,
) => ReactElement)
className'qui-number-input__input-group'data-disableddata-focusdata-invaliddata-number-input-part'input-group'data-readonlydata-size| 'sm'
| 'md'
| 'lg'
<NumberInput.Input>
className'qui-number-input__input'data-disableddata-emptydata-invaliddata-number-input-part'input'data-size| 'sm'
| 'md'
| 'lg'
<NumberInput.Control>
| ReactElement
| ((
props: object,
) => ReactElement)
className'qui-number-input__control'data-disableddata-focusdata-invaliddata-number-input-part'control'data-size| 'sm'
| 'md'
| 'lg'
<NumberInput.IncrementTrigger>
| ReactElement
| ((
props: object,
) => ReactElement)
className'qui-number-input__step-trigger'data-disableddata-number-input-part'increment-trigger'data-size| 'sm'
| 'md'
| 'lg'
tabIndex-1
<NumberInput.DecrementTrigger>
| ReactElement
| ((
props: object,
) => ReactElement)
className'qui-number-input__step-trigger'data-disableddata-number-input-part'decrement-trigger'data-size| 'sm'
| 'md'
| 'lg'
tabIndex-1
<NumberInput.Hint>
string| ReactElement
| ((
props: object,
) => ReactElement)
data-disableddata-number-input-part'hint'hiddenboolean<NumberInput.ErrorText>
| LucideIcon
| ReactNode
| ReactElement
| ((
props: object,
) => ReactElement)
data-number-input-part'error-text'hiddenboolean<NumberInput.ErrorIndicator>
| LucideIcon
| ReactNode
| ReactElement
| ((
props: object,
) => ReactElement)
className'qui-number-input__error-indicator'data-number-input-part'error-indicator'data-size| 'sm'
| 'md'
| 'lg'
hiddenboolean<NumberInput.UnitSelect>
stringclassName'qui-number-input__unit-select'data-disableddata-number-input-part'unit-select'data-readonlydata-size| 'sm'
| 'md'
| 'lg'
Data Structures
UnitOption
Each unit option object accepts the following properties:
stringstringstring