# Hand Count
URL: https://remocn.dev/docs/typography/hand-count

A number that counts up in stop-motion poses, rewritten by hand at every pose

- Install: `npx shadcn@latest add @remocn/hand-count`
- Vibe: paper
- Natural length: 54f @ 30fps

## Installation

```bash
npx shadcn@latest add @remocn/hand-count
```

## Usage

Every pose the value advances and the digits are **written again** — same
number, different hand. That re-drawing is the whole illusion, and it is what
separates this from every other number in the registry: `rolling-number` and
`number-wheel` glide a mechanical typeface, which is right for a product UI and
wrong for a paper scene.

The component fills its parent with `position: absolute; inset: 0`, so give it
a frame and it centres itself inside it.

```tsx
// src/Root.tsx
import { AbsoluteFill, Composition, Sequence } from "remotion";
import { HandCount, handCountDuration } from "@/components/remocn/hand-count";

const COUNT_AT = 12;
const COUNT_FOR = 14;
const COUNT_ENDS = handCountDuration({
  delay: COUNT_AT,
  durationSteps: COUNT_FOR,
});

const PricingScene = () => (
  <AbsoluteFill style={{ background: "#f1eee7" }}>
    <Sequence durationInFrames={COUNT_ENDS + 30}>
      <HandCount
        to={19}
        delay={COUNT_AT}
        durationSteps={COUNT_FOR}
        prefix="$"
        decimals={2}
        suffix="/mo"
      />
    </Sequence>
  </AbsoluteFill>
);

export const RemotionRoot = () => (
  <Composition
    id="HandCount"
    component={PricingScene}
    durationInFrames={COUNT_ENDS + 30}
    fps={30}
    width={1280}
    height={720}
  />
);
```

### A year-in-review stat

The affixes are written in the same hand as the digits, so a unit reads as part
of the number rather than a label stuck beside it.

```tsx
<div style={{ position: "relative", width: 720, height: 220 }}>
  <HandCount to={1284} suffix=" commits" durationSteps={18} fontSize={120} />
</div>
```

### Sizing the scene

`handCountDuration` returns the frame the number actually **settles** on, which
is not always `delay + durationSteps * step`. The stop-motion clock saturates on
the quantized frame, so an off-grid `delay` pushes the landing to the next pose
boundary — a `<Sequence>` sized by the naive sum can cut up to `step - 1` frames
before the number arrives.

```tsx
handCountDuration({ delay: 0, durationSteps: 12, step: 3 }); // 36
handCountDuration({ delay: 1, durationSteps: 12, step: 3 }); // 39, not 37
```

Keep `delay` a multiple of `step` and the two agree.

### Choosing the ease

`in-out` is the default and it is the one to keep for a headline number. It
opens on a barely-there move, does most of the counting through the middle, and
settles gently — so every pose in the run carries a visible digit change.

`out` front-loads the movement hard: at twelve poses it puts almost a quarter
of the count into the very first pose and leaves the last third of the run
barely moving. That is right when the number is a supporting detail arriving
under something else, and wrong when it is the thing being watched.

A literal spring is deliberately not on offer here. Springs start fast by
construction, which is the same problem as `out`, and the overshoot would show
a price climbing past its own figure before falling back to it.

### Landing and holding still

The value lands on `to` exactly — it never stops at 99.7 — and the jitter
freezes the moment it does. A headline number that keeps twitching for the rest
of the shot is a distraction, not a texture; ambient motion in this kit is
`paper-wobble`'s job.

## Props

| Prop | Type | Default | Description |
|---|---|---|---|
| `to` (required) | `number` | — | Value the count lands on, exactly |
| `from` | `number` | `0` | Value it starts at; above `to` it counts down |
| `delay` | `number` | `0` | Local frame counting starts; keep it a multiple of step |
| `durationSteps` | `number` | `18` | Poses spent counting |
| `decimals` | `number` | `0` | Decimal places; 0 never renders a decimal point |
| `prefix` | `string` | `""` | Written before the number in the same hand |
| `suffix` | `string` | `""` | Written after the number in the same hand |
| `fontSize` | `number` | `96` | Size of the written number |
| `color` | `string` | `"#26242c"` | Ink colour |
| `weight` | `400 \| 500 \| 600 \| 700` | `700` | Font weight |
| `ease` | `"in-out" \| "out" \| "linear"` | `"in-out"` | Shape of the count; `in-out` starts and settles gently, `out` front-loads the movement |
| `align` | `"left" \| "center"` | `"center"` | Alignment inside the frame it fills |
| `fontFamily` | `string` | `Caveat` | Override the handwritten face |
| `seed` | `string` | `"count"` | Seed for the per-pose glyph jitter |
| `step` | `number` | `3` | Frames per stop-motion pose |

## Use when
- A stat, price, or count belongs in a hand-made scene — the number should arrive by being written, not by rolling.
- A paper pricing reveal or year-in-review needs its figure in the same voice as the rest of the shot.
- You want a unit or currency written in the same hand as the digits — `prefix` and `suffix` jitter along with them.

## Don't use when
- The scene is a slick product UI or a dashboard metric — use `rolling-number` or `number-wheel`, which glide a mechanical typeface.
- You need per-digit odometer choreography — that is `number-wheel`'s job.
- You need locale grouping separators (`1,000`) or full currency formatting; `prefix` and `decimals` are the whole surface here.