Motion Hooksregistry/hooks/use-on-twos.ts/r/use-on-twos.json

useOnTwos

Core motion hooks (useOnTwos, useCountUp, useChanged, useSize, useReducedMotion) that sample transitions at 12 poses per second (83.33ms per pose).

Light · Paper.f12-theme-light
Interactive preview
useOnTwos progress: 1.00 · changed: false

$32,805

Dark · Flashback.f12-theme-dark
Interactive preview
useOnTwos progress: 1.00 · changed: false

$32,805

Install & copy-in source

shadcn CLI (use-on-twos.json)
npx shadcn@latest add https://frame12.dev/r/use-on-twos.json
Usage example (useOnTwos)
import { useOnTwos, useCountUp, useChanged } from '@/hooks/use-on-twos';

export function AnimatedStat({ value }: { value: number }) {
  const shown = useCountUp(value, 'stepped', 600);
  const changed = useChanged(value);
  const progress = useOnTwos(value, 600, 'stepped');
  return <output data-changed={changed} data-p={progress.toFixed(2)}>{Math.round(shown)}</output>;
}
WCAG AAAccessibility guarantees

Accessibility notes

  • useReducedMotion() listens to (prefers-reduced-motion: reduce) and forces instant hard cuts.
  • Returns 1 on initial mount so pages render complete at rest with zero layout shift.
GrammarFRAME/12 rules

Design grammar

  • Quantizes elapsed time into FRAME_MS = 1000 / 12 (83.33ms) steps and applies cubic easeOut.

Props & TypeScript API

Exported from @/hooks/use-on-twos (registry/hooks/use-on-twos.ts)
PropTypeDefaultDescription
keyunknownrequiredDependency value; changing key replays the 0..1 progress transition.
durationnumber600Total transition duration in milliseconds.
motion'stepped' | 'smooth' | 'cut''stepped'Sampling mode: 12fps stepped poses, 60fps continuous, or instant hard cut.