#302
Odometer roll
A KPI value made of digit columns that slide to the new digit, the ones place first and each column 60ms after the last. It cycles through values on its own; typing a number rolls it.
Hand this to your AI. It names the exact library parts, timings and accessibility promises of this demo.
Build the "Odometer roll" pattern (@codeatlasdev/ui demo #302, motion/text) in my app.
Call get_demo({ ids: ["#302"] }) first and keep its structure. It needs @codeatlasdev/[email protected].
Use: Dashboards, revenue and counter KPIs, price changes, scores and any number that updates in place and should feel like a mechanical counter.
Keep these library parts, with the props and tokens the demo uses:
- MotionStage, MotionCtx from "@codeatlasdev/ui"
Behaviour to keep:
- `MotionStage` from `@codeatlasdev/ui` with `label="Odometer: a KPI value rolls digit by digit"` and `loop={2600}`
- Each digit is a `.odo__col` window (`overflow: hidden`, `block-size: 1em`) holding a strip of `0` to `9`
- `transform: translateY(calc(var(--d) * -1em))` slides the strip to the digit `--d`
- `transition: transform 900ms cubic-bezier(0.2, 0.9, 0.2, 1) calc(var(--i) * 60ms)` with `--i` counted from the right, so the ones place rolls first
- `role="img"` with `aria-label` carries the whole number once; the columns are `aria-hidden="true"`
- `oninput={onType}` sets `value`: typing a number in the field is the takeover and rolls the columns
- `{@attach autoplay(m)}` walks `values[cycle % values.length]` only while `playing`; under reduced motion `class:odo__strip--run={!m.reduced}` drops the transition and the last value is shown
Exact motion (do not approximate):
- transform: translateY (digit strip inside an overflow window): 900ms, cubic-bezier(0.2, 0.9, 0.2, 1), stagger calc(var(--i) * 60ms)
Reduced motion: the demo handles it; keep that branch.
Keyboard: operable; keep the focus order and key handling.
Change only the copy and the data. Use the theme tokens (--ca-*), never raw colours. Library parts
- MotionStage
@codeatlasdev/ui
How it is built
- `MotionStage` from `@codeatlasdev/ui` with `label="Odometer: a KPI value rolls digit by digit"` and `loop={2600}`
- Each digit is a `.odo__col` window (`overflow: hidden`, `block-size: 1em`) holding a strip of `0` to `9`
- `transform: translateY(calc(var(--d) * -1em))` slides the strip to the digit `--d`
- `transition: transform 900ms cubic-bezier(0.2, 0.9, 0.2, 1) calc(var(--i) * 60ms)` with `--i` counted from the right, so the ones place rolls first
- `role="img"` with `aria-label` carries the whole number once; the columns are `aria-hidden="true"`
- `oninput={onType}` sets `value`: typing a number in the field is the takeover and rolls the columns
- `{@attach autoplay(m)}` walks `values[cycle % values.length]` only while `playing`; under reduced motion `class:odo__strip--run={!m.reduced}` drops the transition and the last value is shown
Related
Loading source.