- Accordion
- Action Bar
- Action Toast
- Alert Banner
- Alert Dialog
- Alert
- Alphabet Index
- Amount Field
- Aspect Ratio
- Attachment
- Availability List
- Avatar
- Badge
- Bank Card
- Breadcrumb
- Bubble
- Button Group
- Button
- Calendar
- Camera Frame
- Card Design Picker
- Card Details
- Card Peek
- Card Stack
- Card
- Carousel
- Chart
- Chat Thread
- Checkbox
- Chip Group
- Choice Tile
- Code Block
- Code Dots
- Collapsible
- Combobox
- Command
- Context Menu
- Copy Field
- Countdown
- Country Select
- Data Table
- Date Field
- Date Picker
- Date Range Picker
- Dialog
- Direction
- Document Paper
- Drawer
- Dropdown Menu
- Empty
- Entity Avatar
- Field
- File Trigger
- File Upload Item
- Hover Card
- Input Group
- Input OTP
- Input
- Item
- Kbd
- Key Value
- Keypad
- Label
- Live Region
- Marker
- Message Scroller
- Message
- Money Amount
- Native Select
- Number Field
- Pagination
- Percent Split Editor
- Phone Field
- Popover
- Progress
- QR Code
- Questionnaire
- Radio Group
- Range Histogram
- Rating
- Resizable
- Scroll Area
- Search Field
- Select
- Separator
- Share Bar
- Sheet
- Sidebar
- Skeleton
- Slider
- Sonner
- Sortable List
- Spinner
- Status Timeline
- Step Header
- Steps List
- Swipe Row
- Switch
- Table
- Tabs
- Text Field
- Textarea
- Tier Ladder
- Toggle Group
- Toggle
- Token Search Field
- Tooltip
- Trace
- Transaction Row
- Usage Meter
"use client"
import {NumberField is a number input on React Aria NumberField, with a minus and a plus button around the value. It parses and formats by locale, keeps the value inside minValue and maxValue, snaps to step, and turns a button off at its limit. Use it for counts and small limits, such as the number of payments, cards to order or a per-payment limit in steps of $50. For an amount of money typed freely, use AmountField instead.
Installation#
pnpm dlx shadcn@latest add @dots/number-field
Usage#
import {
NumberField,
NumberFieldDecrement,
NumberFieldDescription,
NumberFieldGroup,
NumberFieldIncrement,
NumberFieldInput,
NumberFieldLabel,
} from "@/components/ui/number-field"<NumberField defaultValue={4} minValue={1} maxValue={12}>
<NumberFieldLabel>Number of payments</NumberFieldLabel>
<NumberFieldGroup>
<NumberFieldDecrement />
<NumberFieldInput />
<NumberFieldIncrement />
</NumberFieldGroup>
<NumberFieldDescription>From 1 to 12.</NumberFieldDescription>
</NumberField>Composition#
Use the following composition to build a number field:
NumberField
├── NumberFieldLabel
├── NumberFieldGroup
│ ├── NumberFieldDecrement
│ ├── NumberFieldInput
│ └── NumberFieldIncrement
├── NumberFieldDescription
└── NumberFieldErrorFeatures#
- Locale-aware parsing and formatting, including currency, percent and units through
formatOptions minValue,maxValueandstep, with typed values snapped to the step on blur- Minus and plus buttons that turn off at the limits
- Arrow keys and Page Up/Page Down step by
step, and Home and End jump tominValueandmaxValuewhen set - Buttons stay out of the Tab order, and tapping them does not open the phone keyboard
- Label, description and error wired to the input by React Aria
- Controlled and uncontrolled use
Currency#
Pass formatOptions with style: "currency" to show the value as money. Combine it with step for limits that move in fixed amounts.
"use client"
import * as React from "react"<NumberField
value={limit}
onChange={setLimit}
minValue={50}
maxValue={5000}
step={50}
formatOptions={{ style: "currency", currency: "USD", maximumFractionDigits: 0 }}
>
{/* label, group, description */}
</NumberField>Unit#
Use style: "unit" for counts with a unit, such as weeks between repeat payments.
"use client"
import {Invalid#
Set isInvalid from your own rule and render NumberFieldError to say what to fix. minValue and maxValue clamp the value instead of flagging it, so leave maxValue off when you want to show an error for a value that is too high, as this demo does.
"use client"
import * as React from "react"Disabled#
Set isDisabled to turn off the input and both buttons. Keep a description that says why.
"use client"
import {Accessibility#
React Aria renders the input with role="textbox" and an aria-roledescription of "Number field" (except on iOS), links it to NumberFieldLabel, NumberFieldDescription and NumberFieldError, and gives the buttons localized names such as "Decrease" and "Increase" that include the field label.
- Always render
NumberFieldLabel, or passaria-labeltoNumberFieldwhen there is no visible label. - Put the limits in
NumberFieldDescription, so they are read with the field. - Say how to fix the value in
NumberFieldError, not only that it is wrong. - The buttons are left out of the Tab order, so keyboard users step with the arrow keys from the input. Screen reader users can still reach the buttons by swiping.
API Reference#
NumberField#
The root. Wraps React Aria NumberField and accepts all of its props. The most used ones are listed here.
| Prop | Type | Default | Description |
|---|---|---|---|
value | number | - | The value when controlled. |
defaultValue | number | - | The starting value when uncontrolled. |
onChange | (value: number) => void | - | Called when the value is committed: on step, blur or Enter. |
minValue | number | - | The smallest allowed value. |
maxValue | number | - | The largest allowed value. |
step | number | 1 | The amount the buttons and arrow keys change the value by. |
formatOptions | Intl.NumberFormatOptions | - | How the value is formatted and parsed, e.g. currency or unit. |
isDisabled | boolean | - | Turns off the input and buttons. |
isReadOnly | boolean | - | The value can be read and copied but not changed. |
isRequired | boolean | - | A value is required before the form submits. |
isInvalid | boolean | - | Shows the invalid state and NumberFieldError. |
validationBehavior | "native" | "aria" | "native" | aria shows errors in real time instead of on submit. |
name | string | - | The name of the value in a form submit. |
className | string | - | Additional classes to apply to the root. |
NumberFieldLabel#
The field label. Renders a Label and accepts all of its props.
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional classes to apply to the label. |
NumberFieldGroup#
The surface that holds the buttons and the input. It is the kit's InputGroup, on React Aria Group, and takes the disabled and invalid state from the field.
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional classes to apply to the group. |
NumberFieldInput#
The number itself, centered between the buttons with tabular digits. Renders an InputGroupInput and accepts all of its props. Pass ref to focus it.
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional classes to apply to the input. |
NumberFieldDecrement#
Lowers the value by step. Renders an InputGroupButton with a minus icon in a start addon. Its accessible name comes from React Aria.
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional classes to apply to the button. |
...props | React.ComponentProps<typeof InputGroupButton> | - | Button props, except slot, children, size and variant. |
NumberFieldIncrement#
Raises the value by step. Renders an InputGroupButton with a plus icon in an end addon. Its accessible name comes from React Aria.
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional classes to apply to the button. |
...props | React.ComponentProps<typeof InputGroupButton> | - | Button props, except slot, children, size and variant. |
NumberFieldDescription#
Help under the field, such as the limits. Renders React Aria Text with slot="description".
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional classes to apply to the description. |
NumberFieldError#
Says what to fix. Renders React Aria FieldError and shows only while the field is invalid.
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | (validation: ValidationResult) => ReactNode | - | The message. Defaults to the browser's validation message. |
className | string | - | Additional classes to apply to the error. |