Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/apursley2012/magical/llms.txt

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

CustomCursor replaces the browser’s native pointer with two layered elements — a sharp mint dot and a diffuse violet glow orb — both driven by Framer Motion spring physics. It automatically detects when the pointer hovers over interactive elements and responds with a scale transformation, giving users tactile visual feedback.

Device Detection

The component only renders on pointer-fine devices (i.e. mice and trackpads). On touch screens and stylus-only devices, it returns null immediately, leaving the default touch interaction model intact. Detection is performed by checking the (pointer: fine) media query via the browser’s matchMedia API on mount. No cursor elements are ever added to the DOM on non-fine-pointer devices.
You can safely test the portfolio on a touch device or mobile emulator — CustomCursor renders nothing and adds no event listeners, so there is zero performance overhead on touch sessions.

Cursor Elements

Two motion.div elements are rendered at position: fixed, anchored to top-0 left-0 and translated to follow the pointer. Each element is offset by half its own size so it stays centered on the cursor position — the dot animates to x: mouseX - 6, y: mouseY - 6 (half of 12 px) and the glow orb to x: mouseX - 64, y: mouseY - 64 (half of 128 px):

Dot

PropertyValue
Sizew-3 h-3 (12 × 12 px)
Colourbg-mystic-mint
Z-indexz-[100]
Blend modemix-blend-screen
Spring stiffness500
Spring damping28
Spring mass0.5
Scale on hover0.5×
The high stiffness and low mass make the dot feel snappy and tightly coupled to the physical pointer position.

Glow Orb

PropertyValue
Sizew-32 h-32 (128 × 128 px)
Colourbg-mystic-violet/10
Blurblur-xl
Z-indexz-[99]
Spring stiffness250
Spring damping20
Spring mass0.8
Scale on hover1.5×
The softer spring settings give the orb a gentle lag behind the dot, creating a trailing depth effect. On hover, it blooms outward to 1.5× its normal size, making the surrounding glow more prominent.

Hover Detection

The component attaches a mouseover listener to window and checks whether the element under the pointer matches any of the following selectors:
a, button, [role=button], input, textarea, select
When a match is found, the hovering state is set to true, triggering the scale transforms on both cursor elements simultaneously. Moving off an interactive element resets both to their default scales.

Required CSS

For the custom cursor to display correctly, the native browser cursor must be hidden globally for pointer-fine sessions. Add the following rule to your global stylesheet:
@media (pointer: fine) {
  body, a, button, [role=button], input, select, textarea {
    cursor: none;
  }
}
Without this rule, both the browser’s default cursor and the custom cursor will appear on top of each other.

Usage

Place <CustomCursor /> once near the root of your app, outside any scroll containers, so its position: fixed elements are anchored to the viewport:
import { CustomCursor } from './components/CustomCursor';

<CustomCursor />

Build docs developers (and LLMs) love