proNew153 lines · framer-motion
Cursor Text Label
The pointer tells you what it's about to do. A bounded demo section split into a few labelled tiles. While the pointer stays inside the section, the default cursor is replaced by a spring-smoothed pill that follows it and reads out contextual text for whichever tile is underneath.
- Use it for
- A features or capabilities grid where each tile has a distinct action, and a small amount of pointer feedback helps a visitor understand what hovering will do before they click.
- Themes
- Light + dark
- License
- Commercial use
Live
Cursor
A pointer that explains itself
DragReorder this tile freely.
ViewOpen the full preview.
PlayStart the showcase reel.
LinkFollow this reference out.
tsx
"use client";
import * as React from "react";
import { motion, useMotionValue, useReducedMotion, useSpring } from "framer-motion";
import { cn } from "@/lib/utils";
function useReducedMotionSafe() {
const prefersReduced = useReducedMotion();
const [mounted, setMounted] = React.useState(false);
React.useEffect(() => setMounted(true), []);
return mounted ? !!prefersReduced : false;
}
/**
* Bounded demo section with a few labelled zones. While the pointer is inside the
* section (and only inside it), the real cursor hides and a small spring-smoothed
* pill follows it, reading contextual text for whichever zone is underneath.
* Falls back to the plain default cursor on touch devices and under
* prefers-reduced-motion — no custom tracking runs in either case.
*/
export interface CursorTextLabelZone {The rest is in Pro.
Full source, the rebuild prompt and registry install unlock with Pro or Lifetime.
Get ProHow it behaves
- →onPointerMove/onPointerEnter/onPointerLeave on the section's own root track the pointer only while it is inside that element; nothing is attached to window or document.
- →Pointer position drives a framer-motion useMotionValue pair smoothed with useSpring, so the pill lags gently behind the real pointer instead of snapping to it.
- →The pill's text swaps per tile via a data-cursor-zone attribute read through event.target.closest; hovering empty space inside the section shows the neutral idleText instead.
- →The pill scales and fades in on enter and out on leave via a framer-motion animate transition.
- →cursor: none is applied to the section element itself, and only once pointer/hover media queries have confirmed a fine pointer is present; it is removed the instant the pointer leaves the section.
- →On touch devices (pointer: coarse or hover: none) and under prefers-reduced-motion, the whole effect is skipped and the section renders with the plain default cursor.
Accessibility
- ✓The floating pill is `aria-hidden` and `pointer-events-none`; it never enters the accessibility tree or intercepts clicks.
- ✓Tiles remain plain content elements with visible text, so the zone labels and descriptions are readable without the pointer effect.
- ✓No custom cursor or `cursor: none` is ever applied outside the section, and never to `<body>`/`<html>`, so keyboard and touch users keep the native cursor everywhere else.
- ✓Honours prefers-reduced-motion.