NumberInput
Migration guide for NumberInput to NumberField from HeroUI v2 to v3
Refer to the v3 NumberField documentation for complete API reference, styling guide, and advanced examples. This guide only focuses on migrating from HeroUI v2.
Overview
The NumberInput component in HeroUI v3 has been renamed to NumberField and redesigned with a compound component pattern, requiring explicit structure with NumberField.Group, NumberField.Input, NumberField.IncrementButton, and NumberField.DecrementButton components.
Structure Changes
v2: Single Component
In v2, NumberInput was a single component with props:
import { NumberInput } from "@heroui/react";
<NumberInput label="Amount" defaultValue={1024} />v3: Compound Components
In v3, NumberField requires compound components:
import { NumberField, Label } from "@heroui/react";
<NumberField defaultValue={1024}>
<Label>Amount</Label>
<NumberField.Group>
<NumberField.DecrementButton />
<NumberField.Input />
<NumberField.IncrementButton />
</NumberField.Group>
</NumberField>Key Changes
1. Component Naming
v2: NumberInput
v3: NumberField
2. Component Structure
v2: Single component with props
v3: Compound components: NumberField.Group, NumberField.Input, NumberField.IncrementButton, NumberField.DecrementButton
3. Prop Changes
| v2 Prop | v3 Prop | Notes |
|---|---|---|
onValueChange | onChange | Renamed event handler |
label | - | Removed (use Label component) |
description | - | Removed (use Description component) |
errorMessage | - | Removed (use FieldError component) |
variant | - | Removed (use Tailwind CSS) |
color | - | Removed (use Tailwind CSS) |
size | - | Removed (use Tailwind CSS) |
radius | - | Removed (use Tailwind CSS) |
startContent | - | Removed (place manually) |
endContent | - | Removed (place manually) |
labelPlacement | - | Removed (handle with layout) |
hideStepper | - | Omit stepper buttons instead |
isClearable | - | Removed (handle manually) |
classNames | - | Use className props |
isWheelDisabled | - | Removed |
4. Removed Props
The following props are no longer available in v3:
label- UseLabelcomponent insteaddescription- UseDescriptioncomponent insteaderrorMessage- UseFieldErrorcomponent insteadvariant- Use Tailwind CSS classescolor- Use Tailwind CSS classessize- Use Tailwind CSS classesradius- Use Tailwind CSS classesstartContent- Place content manually in GroupendContent- Place content manually in GrouplabelPlacement- Handle with layout classeshideStepper- OmitNumberField.IncrementButtonandNumberField.DecrementButtonisClearable- Handle clear functionality manuallyclassNames- UseclassNameprops on individual componentsisWheelDisabled- Removed
Migration Examples
Basic Usage
import { NumberInput } from "@heroui/react";
export default function App() {
return (
<NumberInput label="Amount" defaultValue={1024} />
);
}import { NumberField, Label } from "@heroui/react";
export default function App() {
return (
<NumberField defaultValue={1024}>
<Label>Amount</Label>
<NumberField.Group>
<NumberField.DecrementButton />
<NumberField.Input />
<NumberField.IncrementButton />
</NumberField.Group>
</NumberField>
);
}With Description
<NumberInput
description="Enter the amount"
label="Amount"
/>import { Description, Label } from "@heroui/react";
<NumberField>
<Label>Amount</Label>
<NumberField.Group>
<NumberField.DecrementButton />
<NumberField.Input />
<NumberField.IncrementButton />
</NumberField.Group>
<Description>Enter the amount</Description>
</NumberField>With Error Message
<NumberInput
errorMessage="Please enter a valid number"
isInvalid
label="Amount"
/>import { FieldError, Label } from "@heroui/react";
<NumberField isInvalid>
<Label>Amount</Label>
<NumberField.Group>
<NumberField.DecrementButton />
<NumberField.Input />
<NumberField.IncrementButton />
</NumberField.Group>
<FieldError>Please enter a valid number</FieldError>
</NumberField>Controlled
import { useState } from "react";
const [value, setValue] = useState();
<NumberInput
value={value}
onValueChange={setValue}
/>import { useState } from "react";
const [value, setValue] = useState<number | undefined>();
<NumberField value={value} onChange={setValue}>
<Label>Amount</Label>
<NumberField.Group>
<NumberField.DecrementButton />
<NumberField.Input />
<NumberField.IncrementButton />
</NumberField.Group>
</NumberField>Without Stepper Buttons
<NumberInput hideStepper label="Amount" /><NumberField>
<Label>Amount</Label>
<NumberField.Group>
<NumberField.Input />
</NumberField.Group>
</NumberField>With Min/Max Values
<NumberInput
label="Quantity"
maxValue={100}
minValue={0}
/><NumberField maxValue={100} minValue={0}>
<Label>Quantity</Label>
<NumberField.Group>
<NumberField.DecrementButton />
<NumberField.Input />
<NumberField.IncrementButton />
</NumberField.Group>
</NumberField>With Step Value
<NumberInput label="Percentage" step={0.1} /><NumberField step={0.1}>
<Label>Percentage</Label>
<NumberField.Group>
<NumberField.DecrementButton />
<NumberField.Input />
<NumberField.IncrementButton />
</NumberField.Group>
</NumberField>With Format Options
<NumberInput
formatOptions={{style: "currency", currency: "USD"}}
label="Price"
/><NumberField formatOptions={{style: "currency", currency: "USD"}}>
<Label>Price</Label>
<NumberField.Group>
<NumberField.DecrementButton />
<NumberField.Input />
<NumberField.IncrementButton />
</NumberField.Group>
</NumberField>Required Field
<NumberInput isRequired label="Quantity" /><NumberField isRequired>
<Label>Quantity</Label>
<NumberField.Group>
<NumberField.DecrementButton />
<NumberField.Input />
<NumberField.IncrementButton />
</NumberField.Group>
</NumberField>Disabled State
<NumberInput isDisabled label="Amount" /><NumberField isDisabled>
<Label>Amount</Label>
<NumberField.Group>
<NumberField.DecrementButton />
<NumberField.Input />
<NumberField.IncrementButton />
</NumberField.Group>
</NumberField>Custom Styling
<NumberInput
classNames={{
base: "custom-base",
input: "custom-input"
}}
label="Amount"
/><NumberField className="custom-base">
<Label>Amount</Label>
<NumberField.Group>
<NumberField.DecrementButton />
<NumberField.Input className="custom-input" />
<NumberField.IncrementButton />
</NumberField.Group>
</NumberField>Component Anatomy
The v3 NumberField follows this structure:
NumberField (Root)
├── Label (optional)
├── NumberField.Group
│ ├── NumberField.DecrementButton
│ ├── NumberField.Input
│ └── NumberField.IncrementButton
├── Description (optional)
└── FieldError (optional)Breaking Changes Summary
- Component Renamed:
NumberInput→NumberField - Component Structure: Must use compound components (
NumberField.Group,NumberField.Input, etc.) - Label/Description/Error: Use separate components (
Label,Description,FieldError) - Stepper Buttons: Must explicitly include
NumberField.IncrementButtonandNumberField.DecrementButton - Event Handler:
onValueChange→onChange - Styling Props Removed:
variant,color,size,radius- use Tailwind CSS - Content Props Removed:
startContent,endContent- place manually - Clear Button Removed:
isClearableremoved - handle manually - Stepper Control:
hideStepperremoved - omit buttons instead - Label Placement Removed:
labelPlacementremoved - handle with layout
Tips for Migration
- Update component name: Change
NumberInputtoNumberField - Add compound structure: Wrap input and buttons in
NumberField.Group - Add stepper buttons: Include
NumberField.IncrementButtonandNumberField.DecrementButton - Replace label prop: Use
Labelcomponent instead - Replace description prop: Use
Descriptioncomponent instead - Replace errorMessage prop: Use
FieldErrorcomponent instead - Update event handler: Change
onValueChangetoonChange - Remove hideStepper: Omit stepper buttons if not needed
- Handle clear manually: Implement clear functionality if needed
- Update styling: Use Tailwind CSS classes for variants, colors, sizes
Need Help?
For v3 NumberField features and API:
- See the API Reference
- Check interactive examples
For community support: