Documentation Index
Fetch the complete documentation index at: https://mintlify.com/apursley2012/cosmic-developer/llms.txt
Use this file to discover all available pages before exploring further.
CustomCursor gives the Cosmic Developer portfolio its signature input feel: the native OS cursor is hidden globally, and in its place a three-layer Framer Motion cursor tracks mouse movement with spring physics. The cursor reacts visibly when hovering over links, buttons, or any element marked .interactive, and its mix-blend-screen blending mode keeps it legible against both dark and light surfaces.
Usage
Add<CustomCursor /> once at the root of your application, outside of any scrolling containers. It attaches its own window event listeners and renders three fixed-position elements at the top of the stacking context.
How It Works
Mouse position tracking
A
mousemove listener updates a { x, y } state on every pointer movement. The coordinates are stored as clientX / clientY (viewport-relative), which pairs naturally with position: fixed cursor elements.Interactive state detection
A
mouseover listener checks event.target on every element the cursor enters. The isHovered state is set to true if the target is, or is a descendant of, an <a> or <button>, or if the target has the .interactive class. All other elements set it back to false.The Three Cursor Layers
| Layer | Size | Style | Spring config | z-index |
|---|---|---|---|---|
| Inner dot | w-4 h-4 | bg-aurora-teal, filled circle | stiffness 500, damping 28, mass 0.5 | 9999 |
| Outer ring | w-12 h-12 | border border-aurora-teal/50, hollow circle | stiffness 250, damping 20, mass 0.8 | 9998 |
| Magenta blur | w-2 h-2 | bg-aurora-magenta blur-[2px], soft dot | stiffness 100, damping 30, mass 1.5 | 9997 |
Hover scale
WhenisHovered is true:
- The inner dot scales up to
1.5× - The outer ring scales up to
1.2×and transitions toopacity: 0.8
isHovered is false, the ring drops back to opacity: 0.3.
The .interactive Class
Any element — not just native <a> and <button> tags — can trigger the cursor’s expanded hover state by carrying the interactive class:
mouseover listener checks for .interactive via target.classList.contains('interactive'), so the class must be on the exact element the cursor enters (or a parent that contains it via the closest('a') / closest('button') fallback).
The
closest() fallback means child elements inside a <button> (like an icon <svg>) will still trigger the hover state even without carrying the .interactive class themselves — the listener walks up the DOM tree automatically.mix-blend-screen
The inner dot (thew-4 h-4 teal circle, z-[9999]) uses mix-blend-screen. The outer ring and the magenta blur dot do not carry this class. In screen blending mode, the RGB values of the cursor and the background pixels are combined additively (the formula is 1 - (1-a)(1-b)). This means:
- On dark backgrounds (near
#000000), the cursor colour shows at nearly full saturation. - On light backgrounds (near
#ffffff), the screen blend approaches white, keeping the cursor visible as a bright halo.
Hiding the Native Cursor
CustomCursor alone does not hide the browser’s default arrow cursor. That is handled in main.css: