Animated Number Input

A numeric field where digits roll on change and the value can be scrubbed horizontally or stepped with the keyboard.

Open in v0

Last updated: August 13, 2026

Installation

npx smoothui-cli add animated-number-input

Features

  • Real <input inputMode="decimal"> overlaid on a rendered digit strip, so typing, text selection and browser autofill keep working
  • Only the digits that actually changed roll vertically; the sign, separators and prefix/suffix cross-fade instead
  • Horizontal pointer scrub to change the value, using pointer capture and an ew-resize cursor
  • Full keyboard stepping: Arrow Up/Down (±step), Shift (×10), Alt (÷10), Page Up/Down, and Home/End to jump to min/max
  • Optional +/- stepper buttons
  • Intl.NumberFormatOptions support via format, plus dedicated precision, prefix and suffix props
  • Invalid typed input sets aria-invalid and shakes once instead of silently failing
  • Controlled and uncontrolled modes
  • Respects prefers-reduced-motion

Accessibility

Keyboard Interactions

KeyDescription
Arrow Up / Arrow DownIncrease or decrease the value by step
Shift + Arrow Up/DownIncrease or decrease by step × 10
Alt + Arrow Up/DownIncrease or decrease by step ÷ 10
Page Up / Page DownIncrease or decrease by step × 10
Home / EndJump to min / max (when finite)
EnterCommit the currently typed text

ARIA Attributes

AttributeElementPurpose
role="spinbutton"InputIdentifies the control as a numeric stepper
aria-valuenow / aria-valuemin / aria-valuemaxInputExposes the current value and its bounds
aria-valuetextInputExposes the formatted (prefixed/suffixed) value
aria-invalidInputSet when the typed text fails to parse into a number
aria-labelInputFalls back to "Number input" when no label is provided
<label htmlFor>LabelAssociates the visible label with the input

Screen Reader

  • The visual digit strip is aria-hidden; screen readers only ever read the real input's value via aria-valuetext.
  • The stepper buttons carry explicit aria-labels ("Increase value" / "Decrease value") and are disabled at the bounds.

Reduced Motion

This component respects the prefers-reduced-motion media query via useReducedMotion from Motion. When reduced motion is preferred, digits and prefix/suffix swap instantly (no roll or cross-fade) and the invalid-input shake is skipped entirely.

Props

Created by

Powered by

motion.dev

© 2026 SmoothUI. Built by Eduardo Calvo.