elements
Demos UI Feed Discuss Install
Style System
  • Style
  • Themes
  • Behaviors
Forms
  • Button
  • ButtonGroup
  • Checkbox
  • ColorPicker
  • Combobox
  • Field
  • FileUpload
  • Input
  • InputGroup
  • InputOTP
  • Label
  • NativeSelect
  • NumberInput
  • PasswordInput
  • RadioGroup
  • Select
  • Slider
  • Switch
  • TagsInput
  • Textarea
  • Toggle
  • ToggleGroup
Overlays
  • AlertDialog
  • Command
  • ContextMenu
  • Dialog
  • Drawer
  • DropdownMenu
  • HoverCard
  • Menubar
  • NavigationMenu
  • Popover
  • Sheet
  • Toast
  • Tooltip
Display
  • Accordion
  • Alert
  • AspectRatio
  • Avatar
  • Badge
  • Breadcrumb
  • Card
  • Collapsible
  • Empty
  • Item
  • Kbd
  • Pagination
  • Progress
  • Separator
  • Skeleton
  • Spinner
  • Table
  • Tabs
  • Tree
Layout
  • Carousel
  • Resizable
  • ScrollArea
  • Sidebar
Dates
  • Calendar
  • DatePicker
  • DateRangePicker
  • TimePicker
Data
  • AreaChart
  • BarChart
  • Chart
  • DataTable
  • Kanban
  • LineChart
  • PieChart
  • RadarChart
  • RadialChart
  • VirtualList
Chat
  • Attachment
  • Message
  • MessageList
  • PromptInput
Elements UI / Forms / NumberInput

NumberInput

A number field with stepper buttons, keyboard steps, formatting, wheel and scrub.

Basic

Type a number, or step it with the buttons or ArrowUp and ArrowDown. Shift steps by 10, Alt by 0.1. Hold a button to repeat.

value: 1, changes: 0, commits: 0, reason: , direction: 0
Code
<NumberInput value={state.quantity} attrs={{ "aria-label": "Quantity" }}
             onValueChange={(v, d) => log(d.reason)}
             onValueCommit={() => state.commits++} />

Usage

import { NumberInput } from "@elements/ui/number-input";

<NumberInput value={cart.quantity} min={1} max={99} attrs={{ "aria-label": "Quantity" }} />
<NumberInput value={form.price} format={{ style: "currency", currency: "USD" }} step={0.5} />
<NumberInput value={layer.width} scrubLabel="Width" buttons="end" allowWheelScrub />

Examples

Min and max

Blur clamps a typed value to the bounds and Home and End go to them. allowOutOfRange keeps the typed value and marks it invalid.

5 / 5 change: none, commit: none
Code
<NumberInput value={state.bounded} min={0} max={10} />
<NumberInput value={state.loose} min={0} max={10} allowOutOfRange />

Formats

format takes Intl.NumberFormat options: currency, percent, units. Typing parses in the locale.

12.5 / 0.25 / 1234.5
Code
<NumberInput value={state.price} step={0.25} format={{ style: "currency", currency: "USD" }} />
<NumberInput value={state.rate} step={0.01} min={0} max={1} format={{ style: "percent" }} />
<NumberInput value={state.euro} locale="de-DE" format={{ style: "currency", currency: "EUR" }} />

Snap to step

snapOnStep: a step from 12 with step 5 lands on 15, then 20.

12
Code
<NumberInput value={state.snapped} step={5} snapOnStep />

Scrub and wheel

Drag a scrub label to change the value. allowWheelScrub steps with the wheel while the input is focused and hovered.

24 / 80 / 3 change: none, commit: none
Code
<NumberInput value={state.width} scrubLabel="Width" teleportDistance={60} buttons="end" min={0} step={0.5} format={{ style: "unit", unit: "centimeter" }} />
<NumberInput value={state.height} scrubLabel="Height" scrubDirection="vertical" pixelSensitivity={4} buttons="none" />
<NumberInput value={state.wheel} allowWheelScrub buttons="end" />

Sizes

Heights follow the control tokens.

Code
<NumberInput value={state.small} size="sm" />
<NumberInput value={state.large} size="lg" />

Disabled and read-only

Neither steps. Read-only stays focusable.

Code
<NumberInput value={state.locked} disabled />
<NumberInput value={state.fixed} readonly />

In a form

name submits the raw number. Reset restores the first value; required blocks an empty submit.

not submitted
Code
<form onsubmit={(e) => submit(e)}>
  <NumberInput value={state.qty} name="quantity" min={1} required />
  <Button type="reset">Reset</Button>
  <Button type="submit" variant="primary">Submit</Button>
</form>

In a field

The field's label and description wire to the input.

Between 18 and 120.

Code
<Field label="Age" description="Between 18 and 120.">
  <NumberInput value={state.age} min={18} max={120} />
</Field>

Refusing a change

onValueChange gets details.cancel(): this one keeps even numbers only.

4
Code
<NumberInput value={state.even} step={2}
             onValueChange={(v, d) => v !== null && v % 2 !== 0 && d.cancel()} />
Reference NumberInput in the manual Every part, attribute, slot, key and data attribute.
Prev NativeSelectNext PasswordInput
Product
Manual Pricing Compare
Company
History Contact
Legal
Privacy Policy Acceptable Use Terms License Agreement
© Elements Dev Corporation 2026