Skip to content

Cursor Label Follower

A contextual chip that trails the pointer and names whatever it is over.

Freeminimaleditorialplayful
Category
Components
Added
2026-09-20
Deps
1
Updated
2026-09-20
Preview

Props

420
Leading dot
Requires framer-motion
"use client";

import { useRef, useState } from "react";
import { motion, useMotionValue, useSpring } from "framer-motion";

export function CursorLabelFollower({
  children,
  stiffness = 420,
  showDot = true,
}: {
  children: React.ReactNode;
  stiffness?: number;
  /** The small leading dot inside the chip. */
  showDot?: boolean;
}) {
  const boxRef = useRef<HTMLDivElement>(null);
  const [label, setLabel] = useState<string | null>(null);

  // Motion values, not state: pointer movement writes a transform directly
  // and never re-renders this component.
  const x = useMotionValue(0);
  const y = useMotionValue(0);
  const sx = useSpring(x, { stiffness, damping: 30, mass: 0.35 });
  const sy = useSpring(y, { stiffness, damping: 30, mass: 0.35 });

  function handleMove(e: React.MouseEvent<HTMLDivElement>) {
    const rect = boxRef.current?.getBoundingClientRect();
    if (!rect) return;
    x.set(e.clientX - rect.left);
    y.set(e.clientY - rect.top);
  }

  // Any descendant with data-cursor-label="Something" sets the chip text.
  function handleOver(e: React.MouseEvent<HTMLDivElement>) {
    const target = (e.target as HTMLElement).closest("[data-cursor-label]");
    setLabel(target?.getAttribute("data-cursor-label") ?? null);
  }

  return (
    <div
      ref={boxRef}
      onMouseMove={handleMove}
      onMouseOver={handleOver}
      onMouseLeave={() => setLabel(null)}
      className="relative"
    >
      {children}

      <motion.div
        aria-hidden
        style={{ x: sx, y: sy }}
        className="pointer-events-none absolute left-0 top-0 z-50"
      >
        <motion.div
          initial={false}
          animate={{ opacity: label ? 1 : 0, scale: label ? 1 : 0.7 }}
          transition={{ duration: 0.18, ease: [0.16, 1, 0.3, 1] }}
          className="flex -translate-x-1/2 -translate-y-1/2 items-center gap-1.5 rounded-full bg-blue-600 px-2.5 py-1.5 font-mono text-[10px] uppercase leading-none tracking-[0.12em] text-white"
        >
          {showDot && <span className="size-1 rounded-full bg-white/70" />}
          {label ?? ""}
        </motion.div>
      </motion.div>
    </div>
  );
}
Notes

About this component

A cursor chip that names what it is over does something most custom cursors do not: it carries information. On a portfolio grid or a media gallery, where every tile looks clickable but they do not all do the same thing, it replaces a row of visible button labels with one that only appears where the pointer already is. The mechanism worth copying is the delegation. Rather than attaching enter and leave handlers to every target, one onMouseOver on the wrapper reads event.target.closest with a data attribute selector, so adding a new labelled element is an attribute and nothing else — it scales to a hundred tiles at the cost of one listener. Position rides Framer motion values with a spring, never state, which is what keeps a grid of mounted previews from re-rendering on every pixel of pointer travel. Two caveats: the chip is decorative and hidden from assistive technology, so whatever it says must also exist in the accessible name of the thing it labels, and on touch devices there is no pointer at all, so the underlying affordance has to stand on its own.

Curator’s note

Rebuilt in-house for viberdy 2.0. The delegated data-attribute lookup is the part worth keeping — it scales to a whole gallery without one handler per tile.

Related

Pairs well with

Matched on shared tags and category — the entries most likely to be used alongside this one.

Featured
New

Snapping Cursor

components

A cursor dot that latches onto interactive elements and takes their exact shape.

cursormagneticsnap
Featured

Magnetic Button

components

A button whose label leans toward the cursor with a springy pull.

buttoncursorspring

Tilt Card

components

A 3D card that tilts toward the cursor with spring physics.

card3dcursor