proNew202 lines · framer-motion
Cursor Ring Trail
A chain of rings, each a little further behind. A bounded demo panel where a primary ring and a trail of smaller, fainter rings follow the real pointer, each lagging a touch more than the last — a chain of independent springs, not a single follower.
- Use it for
- Premium hero or feature panels that want a distinctive custom-cursor moment without hijacking the whole page.
- Themes
- Light + dark
- License
- Commercial use
Live
Cursors · Pro
A trail of rings follows you
Each ring lags a little further behind the last, like a chain of springs.
tsx
"use client";
import * as React from "react";
import { motion, useMotionValue, useSpring } from "framer-motion";
import { cn } from "@/lib/utils";
/**
* A bounded demo section: while the real pointer is inside it, a primary ring
* plus a chain of fainter, smaller rings trail it, each lagging further behind
* the last (independent springs with decreasing stiffness per ring). Falls back
* to the plain default cursor on touch devices and when the user prefers
* reduced motion — checked once on mount, no custom effect is attempted then.
*/
export interface CursorRingTrailProps {
heading?: string;
hint?: string;
/** Number of rings in the trail, including the primary one. */
ringCount?: number;
/** How much each ring behind the primary one lags — higher trails further. */
trailLag?: number;
/** Diameter of the primary ring, in px. Trailing rings shrink from this. */The rest is in Pro.
Full source, the rebuild prompt and registry install unlock with Pro or Lifetime.
Get ProHow it behaves
- →A primary ring plus ringCount - 1 trailing rings (simple borders, no fill) follow the pointer; each ring is its own spring off the raw pointer position with progressively lower stiffness, so later rings trail further behind.
- →ringCount sets how many rings render (2–5), trailLag sets how much extra lag each successive ring gets, ringSize sets the primary ring's diameter (trailing rings shrink and fade from it), color picks which token drives the ring colour.
- →The primary ring scales up slightly as pointer speed increases, smoothed through its own spring, for extra polish.
- →Rings fade in on pointer-enter and fade out on pointer-leave inside the panel; they never render or track outside the panel's own element.
- →On mount, checks (pointer: coarse), (hover: none) and prefers-reduced-motion: reduce; if any match, the panel renders as a plain static section with the normal pointer and no rings.
- →cursor: none is applied only to the panel's own element, only once JS has confirmed it is safe — never to <body> or <html>.
Accessibility
- ✓Every ring is `aria-hidden`; rings carry no content and never affect the accessibility tree.
- ✓Heading, copy and buttons are real elements reachable and readable with the effect off, exactly as with it on.
- ✓Falls back to the plain default cursor and a static panel for touch pointers and `prefers-reduced-motion`, so no one is forced to parse a moving trail.
- ✓Honours prefers-reduced-motion.