# NumberField **Category**: react **URL**: https://www.heroui.com/docs/react/components/number-field **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(forms)/number-field.mdx > Number input fields with increment/decrement buttons, validation, and internationalized formatting *** ## Import ```tsx import { NumberField } from '@heroui/react'; ``` ### Usage ```tsx import {Label, NumberField} from "@heroui/react"; export function Basic() { return ( ); } ``` ### Anatomy ```tsx import {NumberField, Label, Description, FieldError} from '@heroui/react'; export default () => ( ) ``` > **NumberField** allows users to enter numeric values with optional increment/decrement buttons. It supports internationalized formatting, validation, and keyboard navigation. ### With Description ```tsx import {Description, Label, NumberField} from "@heroui/react"; export function WithDescription() { return (
Enter the width in pixels Value must be between 0 and 100
); } ``` ### Required Field ```tsx import {Description, Label, NumberField} from "@heroui/react"; export function Required() { return (
Rate from 1 to 10
); } ``` ### Validation Use `isInvalid` together with `FieldError` to surface validation messages. ```tsx import {FieldError, Label, NumberField} from "@heroui/react"; export function Validation() { return (
Quantity must be greater than or equal to 0 Percentage must be between 0 and 100
); } ``` ### Controlled Control the value to synchronize with other components or perform custom formatting. ```tsx "use client"; import {Button, Description, Label, NumberField} from "@heroui/react"; import React from "react"; export function Controlled() { const [value, setValue] = React.useState(1024); return (
Current value: {value}
); } ``` ### With Validation Implement custom validation logic with controlled values. ```tsx "use client"; import {Description, FieldError, Label, NumberField} from "@heroui/react"; import React from "react"; export function WithValidation() { const [value, setValue] = React.useState(undefined); const isInvalid = value !== undefined && (value < 0 || value > 100); return (
{isInvalid ? ( Percentage must be between 0 and 100 ) : ( Enter a value between 0 and 100 )}
); } ``` ### Step Values Configure increment/decrement step values for precise control. ```tsx import {Description, Label, NumberField} from "@heroui/react"; export function WithStep() { return (
Increments by 1 Increments by 5 Increments by 10
); } ``` ### Format Options Format numbers as currency, percentages, decimals, or units with internationalization support. ```tsx import {Description, Label, NumberField} from "@heroui/react"; export function WithFormatOptions() { return (
Accounting format with EUR currency Standard USD currency format Percentage format (0-1, where 0.5 = 50%) Decimal format with 2 decimal places Unit format with kilograms
); } ``` ### Custom Icons Customize the increment and decrement button icons. ```tsx import {Description, Label, NumberField} from "@heroui/react"; export function CustomIcons() { return (
Custom icon children
); } ``` ### With Chevrons Use chevron icons in a vertical layout for a different visual style. ```tsx import {Label, NumberField} from "@heroui/react"; export function WithChevrons() { return (
); } ``` ### Disabled State ```tsx import {Description, Label, NumberField} from "@heroui/react"; export function Disabled() { return (
Enter the width in pixels Value must be between 0 and 100
); } ``` ### Full Width ```tsx import {Label, NumberField} from "@heroui/react"; export function FullWidth() { return (
); } ``` ### Variants The NumberField component supports two visual variants: - **`primary`** (default) - Standard styling with shadow, suitable for most use cases - **`secondary`** - Lower emphasis variant without shadow, suitable for use in Surface components ```tsx import {Label, NumberField} from "@heroui/react"; export function Variants() { return (
); } ``` ### In Surface When used inside a [Surface](/docs/components/surface) component, use `variant="secondary"` to apply the lower emphasis variant suitable for surface backgrounds. ```tsx import {Description, Label, NumberField, Surface} from "@heroui/react"; export function OnSurface() { return ( Enter the width in pixels Value must be between 0 and 100 ); } ``` ### Form Example Complete form integration with validation and submission handling. ```tsx "use client"; import {Button, Description, FieldError, Form, Label, NumberField, Spinner} from "@heroui/react"; import React from "react"; export function FormExample() { const [value, setValue] = React.useState(undefined); const [isSubmitting, setIsSubmitting] = React.useState(false); const STOCK_AVAILABLE = 3; const isOutOfStock = value !== undefined && value > STOCK_AVAILABLE; const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); if (value === undefined || value === null || value < 1 || value > STOCK_AVAILABLE) { return; } setIsSubmitting(true); // Simulate API call setTimeout(() => { console.log("Order submitted:", {quantity: value}); setValue(undefined); setIsSubmitting(false); }, 1500); }; return (
{isOutOfStock ? ( Only {STOCK_AVAILABLE} items left in stock ) : ( Only {STOCK_AVAILABLE} items available )}
); } ``` ## Related Components - **Label**: Accessible label for form controls - **Description**: Helper text for form fields - **FieldError**: Inline validation messages for form fields ### Custom Render Function ```tsx "use client"; import {Label, NumberField} from "@heroui/react"; export function CustomRenderFunction() { return (
} > ); } ``` ## Styling ### Passing Tailwind CSS classes ```tsx import {NumberField, Label} from '@heroui/react'; function CustomNumberField() { return ( ); } ``` ### Customizing the component classes NumberField uses CSS classes that can be customized. Override the component classes to match your design system. ```css @layer components { .number-field { @apply flex flex-col gap-1; } /* When invalid, the description is hidden automatically */ .number-field[data-invalid="true"] [data-slot="description"], .number-field[aria-invalid="true"] [data-slot="description"] { @apply hidden; } .number-field__group { @apply bg-field text-field-foreground shadow-field rounded-field inline-flex h-9 items-center overflow-hidden border; } .number-field__input { @apply flex-1 rounded-none border-0 bg-transparent px-3 py-2 tabular-nums; } .number-field__increment-button, .number-field__decrement-button { @apply flex h-full w-10 items-center justify-center rounded-none bg-transparent; } } ``` ### CSS Classes - `.number-field` – Root container with minimal styling (`flex flex-col gap-1`) - `.number-field__group` – Container for input and buttons with border and background styling - `.number-field__input` – The numeric input field - `.number-field__increment-button` – Button to increment the value - `.number-field__decrement-button` – Button to decrement the value - `.number-field--primary` – Primary variant with shadow (default) - `.number-field--secondary` – Secondary variant without shadow, suitable for use in surfaces > **Note:** Child components ([Label](/docs/components/label), [Description](/docs/components/description), [FieldError](/docs/components/field-error)) have their own CSS classes and styling. See their respective documentation for customization options. ### Interactive States NumberField automatically manages these data attributes based on its state: - **Invalid**: `[data-invalid="true"]` or `[aria-invalid="true"]` - Automatically hides the description slot when invalid - **Disabled**: `[data-disabled="true"]` - Applied when `isDisabled` is true - **Focus Within**: `[data-focus-within="true"]` - Applied when the input or buttons are focused - **Focus Visible**: `[data-focus-visible="true"]` - Applied when focus is visible (keyboard navigation) - **Hovered**: `[data-hovered="true"]` - Applied when hovering over buttons Additional attributes are available through render props (see NumberFieldRenderProps below). ## API Reference ### NumberField Props NumberField inherits all props from React Aria's [NumberField](https://react-spectrum.adobe.com/react-aria/NumberField.html) component. #### Base Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `children` | `React.ReactNode \| (values: NumberFieldRenderProps) => React.ReactNode` | - | Child components (Label, Group, Input, etc.) or render function. | | `className` | `string \| (values: NumberFieldRenderProps) => string` | - | CSS classes for styling, supports render props. | | `style` | `React.CSSProperties \| (values: NumberFieldRenderProps) => React.CSSProperties` | - | Inline styles, supports render props. | | `fullWidth` | `boolean` | `false` | Whether the number field should take full width of its container | | `id` | `string` | - | The element's unique identifier. | | `variant` | `"primary" \| "secondary"` | `"primary"` | Visual variant of the component. `primary` is the default style with shadow. `secondary` is a lower emphasis variant without shadow, suitable for use in surfaces. | | `render` | `DOMRenderFunction` | - | Overrides the default DOM element with a custom render function.| #### Value Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `value` | `number` | - | Current value (controlled). | | `defaultValue` | `number` | - | Default value (uncontrolled). | | `onChange` | `(value: number \| undefined) => void` | - | Handler called when the value changes. | #### Formatting Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `formatOptions` | `Intl.NumberFormatOptions` | - | Options for formatting numbers (currency, percent, decimal, unit). | | `locale` | `string` | - | Locale for number formatting. | #### Validation Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `isRequired` | `boolean` | `false` | Whether user input is required before form submission. | | `isInvalid` | `boolean` | - | Whether the value is invalid. | | `validate` | `(value: number) => ValidationError \| true \| null \| undefined` | - | Custom validation function. | | `validationBehavior` | `'native' \| 'aria'` | `'native'` | Whether to use native HTML form validation or ARIA attributes. | | `validationErrors` | `string[]` | - | Server-side validation errors. | #### Range Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `minValue` | `number` | - | Minimum allowed value. | | `maxValue` | `number` | - | Maximum allowed value. | | `step` | `number` | `1` | Step value for increment/decrement operations. | #### State Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `isDisabled` | `boolean` | - | Whether the input is disabled. | | `isReadOnly` | `boolean` | - | Whether the input can be selected but not changed. | #### Form Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `name` | `string` | - | Name of the input element, for HTML form submission. | | `autoFocus` | `boolean` | - | Whether the element should receive focus on render. | #### Accessibility Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `aria-label` | `string` | - | Accessibility label when no visible label is present. | | `aria-labelledby` | `string` | - | ID of elements that label this field. | | `aria-describedby` | `string` | - | ID of elements that describe this field. | | `aria-details` | `string` | - | ID of elements with additional details. | ### Composition Components NumberField works with these separate components that should be imported and used directly: - **NumberField.Group** - Container for input and buttons - **NumberField.Input** - The numeric input field - **NumberField.IncrementButton** - Button to increment the value - **NumberField.DecrementButton** - Button to decrement the value - **Label** - Field label component from `@heroui/react` - **Description** - Helper text component from `@heroui/react` - **FieldError** - Validation error message from `@heroui/react` Each of these components has its own props API. Use them directly within NumberField for composition: ```tsx Enter a value between 0 and 100 Value must be between 0 and 100 ``` #### NumberField.Group Props NumberField.Group inherits props from React Aria's [Group](https://react-spectrum.adobe.com/react-aria/Group.html) component. | Prop | Type | Default | Description | |------|------|---------|-------------| | `children` | `React.ReactNode \| (values: GroupRenderProps) => React.ReactNode` | - | Child components (Input, Buttons) or render function. | | `className` | `string \| (values: GroupRenderProps) => string` | - | CSS classes for styling. | #### NumberField.Input Props NumberField.Input inherits props from React Aria's [Input](https://react-spectrum.adobe.com/react-aria/Input.html) component. | Prop | Type | Default | Description | |------|------|---------|-------------| | `className` | `string` | - | CSS classes for styling. | | `variant` | `"primary" \| "secondary"` | `"primary"` | Visual variant of the input. `primary` is the default style with shadow. `secondary` is a lower emphasis variant without shadow, suitable for use in surfaces. | #### NumberField.IncrementButton Props NumberField.IncrementButton inherits props from React Aria's [Button](https://react-spectrum.adobe.com/react-aria/Button.html) component. | Prop | Type | Default | Description | |------|------|---------|-------------| | `children` | `React.ReactNode` | `` | Icon or content for the button. Defaults to plus icon. | | `className` | `string` | - | CSS classes for styling. | | `slot` | `"increment"` | `"increment"` | Must be set to "increment" (automatically set). | #### NumberField.DecrementButton Props NumberField.DecrementButton inherits props from React Aria's [Button](https://react-spectrum.adobe.com/react-aria/Button.html) component. | Prop | Type | Default | Description | |------|------|---------|-------------| | `children` | `React.ReactNode` | `` | Icon or content for the button. Defaults to minus icon. | | `className` | `string` | - | CSS classes for styling. | | `slot` | `"decrement"` | `"decrement"` | Must be set to "decrement" (automatically set). | ### NumberFieldRenderProps When using render props with `className`, `style`, or `children`, these values are available: | Prop | Type | Description | |------|------|-------------| | `isDisabled` | `boolean` | Whether the field is disabled. | | `isInvalid` | `boolean` | Whether the field is currently invalid. | | `isReadOnly` | `boolean` | Whether the field is read-only. | | `isRequired` | `boolean` | Whether the field is required. | | `isFocused` | `boolean` | Whether the field is currently focused (DEPRECATED - use `isFocusWithin`). | | `isFocusWithin` | `boolean` | Whether any child element is focused. | | `isFocusVisible` | `boolean` | Whether focus is visible (keyboard navigation). | | `value` | `number \| undefined` | Current value. | | `minValue` | `number \| undefined` | Minimum allowed value. | | `maxValue` | `number \| undefined` | Maximum allowed value. | | `step` | `number` | Step value for increment/decrement. |