Simulated Cursor

A synthetic mouse cursor that travels between waypoints and fires a click ripple, for narrating a UI on screen

Installation
$ pnpm dlx shadcn@latest add @remocn/simulated-cursor

Usage

The cursor walks the points array in order. Each leg takes a fixed 24 frames of travel, then rests for that point's hold (default 15). A point marked click fires a ripple when the cursor arrives.

tsx
// src/Root.tsx
import { Composition } from "remotion";
import { SimulatedCursor } from "@/components/remocn/simulated-cursor";
 
const CursorScene = () => (
  <SimulatedCursor
    points={[
      { x: 200, y: 150, hold: 20 },
      { x: 800, y: 360, hold: 25, click: true },
      { x: 1050, y: 560, hold: 20 },
    ]}
    color="#171717"
    size={28}
  />
);
 
export const RemotionRoot = () => (
  <Composition
    id="SimulatedCursor"
    component={CursorScene}
    durationInFrames={150}
    fps={30}
    width={1280}
    height={720}
  />
);

Over a screenshot

The component renders transparent, so layer it above whatever it is pointing at.

tsx
import { AbsoluteFill, Img, staticFile } from "remotion";
import { SimulatedCursor } from "@/components/remocn/simulated-cursor";
 
const DemoScene = () => (
  <AbsoluteFill>
    <Img src={staticFile("dashboard.png")} style={{ width: "100%", height: "100%" }} />
    <SimulatedCursor
      points={[
        { x: 320, y: 210, hold: 18 },
        { x: 760, y: 420, hold: 24, click: true },
      ]}
      color="#171717"
    />
  </AbsoluteFill>
);

Timing

Budget the Sequence from the waypoints: 24 frames per leg plus each point's hold. The default three-point path runs about 93 frames; leave headroom for the click ripple to finish.

Props5

PropTypeDefault
points
CursorPoint[]DEFAULT_POINTS

Waypoints the cursor travels through, in order. Each is { x, y, hold?, click? } in absolute canvas pixels.

color
string"#ffffff"

Fill color of the cursor arrow. Use a dark value over light UI screenshots.

size
number32

Height of the cursor arrow in pixels.

speed
number1

Time multiplier applied as frame × speed. Above 1 the cursor completes its path sooner.

className
string—

Optional className passed to the wrapper element.

  • pointsCursorPoint[]

    Waypoints the cursor travels through, in order. Each is { x, y, hold?, click? } in absolute canvas pixels.

    DefaultDEFAULT_POINTS

  • colorstring

    Fill color of the cursor arrow. Use a dark value over light UI screenshots.

    Default"#ffffff"

  • sizenumber

    Height of the cursor arrow in pixels.

    Default32

  • speednumber

    Time multiplier applied as frame × speed. Above 1 the cursor completes its path sooner.

    Default1

  • classNamestring

    Optional className passed to the wrapper element.

CursorPoint

PropTypeDefault
xrequired
number—

Horizontal position in canvas pixels.

yrequired
number—

Vertical position in canvas pixels.

hold
number15

Frames the cursor rests at this point after arriving, before starting the next leg.

click
booleanfalse

Fires a click ripple when the cursor arrives at this point.

  • xrequirednumber

    Horizontal position in canvas pixels.

  • yrequirednumber

    Vertical position in canvas pixels.

  • holdnumber

    Frames the cursor rests at this point after arriving, before starting the next leg.

    Default15

  • clickboolean

    Fires a click ripple when the cursor arrives at this point.

    Defaultfalse