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.

// 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}
  />
);
Coordinates are canvas pixels

x and y are absolute pixels on the composition canvas, not normalized 0–1 values. On the standard 1280×720 canvas, { x: 640, y: 360 } is dead center. Change the canvas size and the waypoints move with it.

Over a screenshot

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

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.

Props

PropTypeDefaultDescription
points
CursorPoint[]DEFAULT_POINTSWaypoints 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
number32Height of the cursor arrow in pixels.
speed
number1Time multiplier applied as frame × speed. Above 1 the cursor completes its path sooner.
className
stringOptional className passed to the wrapper element.

CursorPoint

PropTypeDefaultDescription
xrequired
numberHorizontal position in canvas pixels.
yrequired
numberVertical position in canvas pixels.
hold
number15Frames the cursor rests at this point after arriving, before starting the next leg.
click
booleanfalseFires a click ripple when the cursor arrives at this point.