Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/apursley2012/retro-cosmic-arcade/llms.txt

Use this file to discover all available pages before exploring further.

CursorTrail attaches a global mousemove listener and renders a short stream of glowing neon particles that follow the user’s cursor around the page. Each particle is an 8×8px cyan square (h-2 w-2 in Tailwind) with a dual-color glow (#4dffff cyan + #ff4ad8 magenta), fading out with a scale-down animation over 500 ms. The component mounts a fixed, pointer-events-none overlay at z-index 50 so it never interferes with clicks, forms, or other interactive elements.

Props

This component accepts no props. Drop it anywhere in the tree and it self-manages its own state and event listeners.

Usage

Place CursorTrail once, near the root of your application. A good location is your layout shell or App.jsx:
import { CursorTrail } from "@/components/CursorTrail";

function App() {
  return (
    <>
      <CursorTrail />
      {/* rest of your app */}
    </>
  );
}
Do not render CursorTrail more than once simultaneously. Multiple instances will each attach their own mousemove listener and render overlapping particle layers, causing visual doubling and unnecessary re-renders.

How it works

Event listener and particle buffer

On mount, the component registers a single window.addEventListener('mousemove', handler) listener. The handler records the cursor’s clientX / clientY coordinates together with an auto-incrementing numeric id and appends the new position to a React state array. The array is capped at 15 entries by slicing with .slice(-15) — older positions are discarded, creating the trail effect. The listener is cleaned up automatically on unmount via the useEffect return function.

Particle animation

Each particle is rendered as a motion.div inside Framer Motion’s AnimatePresence:
PropertyValue
Width × Height8px × 8px (h-2 w-2)
ShapeSquare (rounded-none)
Fill colorbg-y2k-cyan (#4dffff)
GlowboxShadow: "0 0 5px #4dffff, 0 0 10px #ff4ad8"
initialopacity: 0.8, scale: 1
animateopacity: 0, scale: 0.2
transitionduration: 0.5, ease: "easeOut"

Overlay container

The wrapping <div> uses:
  • fixed inset-0 — covers the full viewport regardless of scroll position.
  • pointer-events-none — all mouse/touch events pass straight through to the content below.
  • z-50 — renders above most other content without requiring manual z-index management.
  • overflow-hidden — clips any particle that spawns at the very edge of the viewport.

Styling notes

  • Particle color is controlled by the bg-y2k-cyan Tailwind token and the inline boxShadow style. To change the trail color, update the custom token in tailwind.config.js and the two hex values in the component’s style prop.
  • The component does not use CSS keyframe animations — all motion is driven by Framer Motion’s JS animation engine for consistent cross-browser behavior.

Dependencies

  • Framer MotionAnimatePresence and motion.div are both required for the enter/exit animations.
CursorTrail uses AnimatePresence to cleanly animate particles out when they are removed from the state array. Without AnimatePresence, particles would simply disappear rather than fade and shrink.
On touch devices, mousemove events are not fired. The component will mount without error but no particles will appear on mobile. This is by design — the effect is purely decorative and desktop-focused.

Build docs developers (and LLMs) love