27.5k

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 Propv3 PropNotes
onValueChangeonChangeRenamed 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 - Use Label component instead
  • description - Use Description component instead
  • errorMessage - Use FieldError component instead
  • variant - Use Tailwind CSS classes
  • color - Use Tailwind CSS classes
  • size - Use Tailwind CSS classes
  • radius - Use Tailwind CSS classes
  • startContent - Place content manually in Group
  • endContent - Place content manually in Group
  • labelPlacement - Handle with layout classes
  • hideStepper - Omit NumberField.IncrementButton and NumberField.DecrementButton
  • isClearable - Handle clear functionality manually
  • classNames - Use className props on individual components
  • isWheelDisabled - 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

  1. Component Renamed: NumberInputNumberField
  2. Component Structure: Must use compound components (NumberField.Group, NumberField.Input, etc.)
  3. Label/Description/Error: Use separate components (Label, Description, FieldError)
  4. Stepper Buttons: Must explicitly include NumberField.IncrementButton and NumberField.DecrementButton
  5. Event Handler: onValueChangeonChange
  6. Styling Props Removed: variant, color, size, radius - use Tailwind CSS
  7. Content Props Removed: startContent, endContent - place manually
  8. Clear Button Removed: isClearable removed - handle manually
  9. Stepper Control: hideStepper removed - omit buttons instead
  10. Label Placement Removed: labelPlacement removed - handle with layout

Tips for Migration

  1. Update component name: Change NumberInput to NumberField
  2. Add compound structure: Wrap input and buttons in NumberField.Group
  3. Add stepper buttons: Include NumberField.IncrementButton and NumberField.DecrementButton
  4. Replace label prop: Use Label component instead
  5. Replace description prop: Use Description component instead
  6. Replace errorMessage prop: Use FieldError component instead
  7. Update event handler: Change onValueChange to onChange
  8. Remove hideStepper: Omit stepper buttons if not needed
  9. Handle clear manually: Implement clear functionality if needed
  10. Update styling: Use Tailwind CSS classes for variants, colors, sizes

Need Help?

For v3 NumberField features and API:

For community support: