Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/apursley2012/fortune-seeker/llms.txt

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

CustomCursor hides the browser’s native cursor and replaces it with a two-part gold cursor — a tight inner dot and a larger outer ring — along with trailing sparkle particles on movement and a star burst animation on click. The component detects when the cursor is hovering over interactive elements (links and buttons) and enlarges both rings accordingly, giving clear affordance without the default OS pointer. It is rendered at the very top of the Layout component at z-index: 100, placing it above all other content.

Props

This component accepts no props. Cursor tracking, interaction detection, and animation are fully self-contained via useEffect and useState.

Usage Example

import CustomCursor from "@/components/CustomCursor";

// CustomCursor is already in Layout; only add it manually
// if you are building a custom shell.
export default function CustomShell({ children }) {
  return (
    <div>
      <CustomCursor />
      {children}
    </div>
  );
}
CustomCursor sets cursor: none implicitly through its pointer-events-none fixed inset-0 overlay approach. To prevent the default cursor from showing through, add cursor-none (or cursor: none in CSS) to the body element in your global stylesheet. Without this, both the native cursor and the custom cursor will be visible simultaneously.

Behavior & Animation

Core Cursor Elements

Two Framer Motion div elements track the mouse position at all times:
ElementSizeDescription
Inner dot0.75rem × 0.75remSolid gold circle (bg-gold), gold glow shadow (0 0 10px #c9a96e), mix-blend-mode: screen.
Outer ring2rem × 2remTransparent circle with a gold border at 50% opacity, mix-blend-mode: screen.
Both elements animate to the current x/y mouse position on every mousemove event. The inner dot uses type: "tween" with ease: "backOut" and duration: 0.1 for near-instant snapping. The outer ring uses ease: "easeOut" with duration: 0.2, creating a slight lag that reinforces the layered feel.

Hover State

On every mousemove, the component checks whether the hovered element is a link or button — by inspecting cursor: pointer in computed styles, the element’s tag name, or closest <a> / <button> ancestors. When isPointer is true:
  • Both the inner dot and outer ring scale to 1.5.
  • The outer ring additionally rotates to 45°, turning the circle into a subtle diamond shape.

Movement Sparkles

On 50% of mousemove events (random gating), a tiny sparkle particle is created at the current cursor position. It animates from opacity: 0.8, scale: 1 to opacity: 0, scale: 0, y: +20px over 0.5s and is then removed from state. A maximum of 16 sparkle particles are retained in state at once (older ones are sliced off), preventing unbounded growth.

Click Burst

On every click event, a star-shaped SVG (24 5-point star path) is spawned at the click coordinates. It animates from opacity: 1, scale: 0.5, rotate: −45° to opacity: 0, scale: 2, rotate: 90° over 1s with easeOut, creating a radiant burst effect. Each burst is keyed by Date.now() and auto-removed after 1000ms via setTimeout. Both the sparkle particles and click bursts are wrapped in Framer Motion AnimatePresence to handle smooth exit animations when they are removed from the DOM.
The component uses mix-blend-mode: screen on all cursor elements. This blend mode makes the gold cursor appear luminous on the dark portfolio background while naturally compositing over lighter content. If you are placing CustomCursor on a white or very light background, consider changing the blend mode to multiply or difference in CustomCursor.js.

Build docs developers (and LLMs) love