Nahorniak Templates
База референсів шаблонів і компонентів
Назад до шаблону · Liko - Creative Agency & Portfolio Next.js Template
c149

magic-cursor

Курсор·Шаблон: Liko - Creative Agency & Portfolio Next.js Template·Складність анімації: heavy·Адаптивний: Ні

Файли-джерела

  • out/index.htmldiv#magic-cursor

Бібліотеки

gsapjquery

Summary

Custom dual-element cursor — a small dot (#magic-cursor) and a larger lerping ball (#ball) — that grow over interactive elements, swap to a "View Demo" label over portfolio thumbs, and hide the native pointer. Activated by adding the tp-magic-cursor class to body.

HTML structure (minimal)

<body class="tp-magic-cursor">
  <div id="magic-cursor">
    <div id="ball"></div>
  </div>
  <!-- Interactive elements opt-in via data-cursor attribute -->
  <div class="tp-project-img not-hide-cursor" data-cursor="View<br>Demo">
    <a class="cursor-hide" href="…"><img src="…" alt=""></a>
  </div>
</body>

Key SCSS tokens

body.tp-magic-cursor, body.tp-magic-cursor * { cursor: none !important; }
#magic-cursor {
  position: fixed; left: 0; top: 0;
  pointer-events: none; z-index: 9999;
  width: 12px; height: 12px;
  border-radius: 50%;
  background: var(--tp-common-black);
}
#ball {
  position: fixed; left: 0; top: 0;
  pointer-events: none;
  width: 60px; height: 60px;
  border-radius: 50%;
  border: 1px solid var(--tp-common-black);
  transition: width .3s, height .3s, background .3s, color .3s;
}
#ball.with-text { width: 120px; height: 120px; background: var(--tp-common-black); color: var(--tp-common-white); display: flex; align-items: center; justify-content: center; text-align: center; }

Animation logic

// src/plugins/tp-cursor.js — invoked from home-1.tsx via cursorAnimation()
// on mount. Listens to mousemove globally, lerps #magic-cursor exactly to
// the pointer and #ball with damping (smooth follow). On mouseenter of any
// [data-cursor] element it adds .with-text and sets innerHTML to that value.
// On mouseleave it resets.
useEffect(() => {
  document.body.classList.add('tp-magic-cursor');
  cursorAnimation();
  return () => document.body.classList.remove('tp-magic-cursor');
}, []);

Notable details

  • Two-layer cursor (sharp dot + soft follower) reads as both a precise pointer and a magnetic ball, which is rare in template land.
  • Opt-in via data-cursor="View<br>Demo" means content authors can change the label without editing JS.
  • cursor-hide class on inner <a> and not-hide-cursor on outer container give per-element control over whether the native cursor shows under the magic one.

Use when

  • Portfolio sites and case-study pages where the cursor itself becomes a UI signal.
  • When you want hovered tiles to communicate intent ("View Demo", "Drag", "Play") without overlay HTML.

Caveats

  • Disabled on touch devices — falls back to the native pointer; do test that interactive elements are still discoverable.
  • cursor: none !important cascades to every child — accessibility audit may flag it; provide a toggle if necessary.