Skip to content
Textlab
1
Browse

ComponentsNumbers

Odometer

A mechanical wheel that spins past every digit.

48,213

Installation

$ npx shadcn@latest add @textlab/odometer

Needs @textlab in your components.json. Setup takes a minute.

Usage

usage.tsx
import { Odometer } from "@/components/textlab/odometer/odometer";

<Odometer value={miles} digits={6} framed />

Variants

mechanicalsmooth

Props

PropTypeDefaultDescription
value*number–A whole, non-negative number.
variant"mechanical" | "smooth""mechanical"mechanical clicks a wheel over only when its neighbour passes 9; smooth spins every wheel continuously.
digitsnumber1Minimum number of wheels, padded with zeros.
durationnumber1.6Seconds to travel to the new value.
easeEaseName | [number, number, number, number]"standard"Easing token or cubic bezier.
framedbooleanfalseThin separators between wheels.
localestring"en-US"Used for the screen-reader label.
asElementType"span"Rendered element.
reducedMotion"user" | "always" | "never""user"user follows the OS setting; always shows the still version.
classNamestring–Merged onto the root.

When to use it

Reach for it

  • Visitor counts, mileage and totals with a physical feel.
  • Big jumps where you want people to sense the distance travelled.

Skip it

  • Currency with decimals; use rolling-number or price-ticker.
  • Negative numbers.

Accessibility and motion

Accessibility

  • Screen readers get the formatted number once; the wheels are aria-hidden.

Motion

  • One motion value drives every wheel, so they always agree.
  • Edges are masked so wheels read as curved drums.
Reduced motion. The new value appears immediately.

Performance

  • One animation per change; wheel positions are derived transforms.