Text Icons Effect
An interactive React component that adds a dynamic bubble effect, visually tracking cursor movement in real time.
An interactive React component that adds a dynamic bubble effect, visually tracking cursor movement in real time.
1// @ts-nocheck2'use client';34import React, { useState } from 'react';5import { useMouse } from '@/hooks/use-mouse';6import { Edit, Search, Play, Link } from 'lucide-react';78const TextIconCursor = () => {9const [mouseState, ref] = useMouse();10const [cursorContent, setCursorContent] = useState(null);1112const icons = {13edit: <Edit size={16} />,14search: <Search size={16} />,15play: <Play size={16} />,16link: <Link size={16} />,17};1819return (20<div className='relative w-full h-full ' ref={ref}>21{mouseState.x !== null && mouseState.y !== null && (22<div23className='fixed pointer-events-none z-50'24style={{25left: mouseState.x,26top: mouseState.y,27transform: 'translate(-50%, -50%)',28}}29>30{/* Main cursor */}31<div className='w-4 h-4 bg-white rounded-full mix-blend-screen' />3233{/* Text/Icon container */}34{cursorContent && (35<div36className='absolute left-6 top-0 bg-white/90 text-gray-900 px-3 py-1.5 rounded-full whitespace-nowrap flex items-center gap-2 text-sm animate-fade-in'37style={{38animation: 'fadeIn 0.2s ease-out',39}}40>41{typeof cursorContent === 'string'42? cursorContent43: icons[cursorContent]}44</div>45)}46</div>47)}4849<div className='flex flex-col items-center justify-center h-full gap-6'>50<button51className='px-6 py-3 bg-white/10 text-white rounded-lg transition-colors'52onMouseEnter={() => setCursorContent('edit')}53onMouseLeave={() => setCursorContent(null)}54>55Edit Button56</button>5758<div59className='px-6 py-3 bg-white/10 text-white rounded-lg cursor-help'60onMouseEnter={() => setCursorContent('Click to search')}61onMouseLeave={() => setCursorContent(null)}62>63Search Area64</div>6566<a67href='#'68className='px-6 py-3 bg-white/10 text-white rounded-lg'69onMouseEnter={() => setCursorContent('link')}70onMouseLeave={() => setCursorContent(null)}71>72Click to Navigate73</a>7475<div76className='w-32 h-32 bg-white/10 rounded-lg flex items-center justify-center'77onMouseEnter={() => setCursorContent('play')}78onMouseLeave={() => setCursorContent(null)}79>80<span className='text-white'>Video Area</span>81</div>82</div>8384<style jsx>{`85@keyframes fadeIn {86from {87opacity: 0;88transform: translateX(-10px);89}90to {91opacity: 1;92transform: translateX(0);93}94}95`}</style>96</div>97);98};99100export default TextIconCursor;101
1npm install lucide-react
1'use client';2import { type RefObject, useLayoutEffect, useRef, useState } from 'react';34interface MouseState {5x: number | null;6y: number | null;7elementX: number | null;8elementY: number | null;9elementPositionX: number | null;10elementPositionY: number | null;11}1213export function useMouse(): [MouseState, RefObject<HTMLDivElement>] {14const [state, setState] = useState<MouseState>({15x: null,16y: null,17elementX: null,18elementY: null,19elementPositionX: null,20elementPositionY: null,21});2223const ref = useRef<HTMLDivElement | null>(null);2425useLayoutEffect(() => {26const handleMouseMove = (event: MouseEvent) => {27const newState: Partial<MouseState> = {28x: event.pageX,29y: event.pageY,30};3132if (ref.current instanceof Element) {33const { left, top } = ref.current.getBoundingClientRect();34const elementPositionX = left + window.scrollX;35const elementPositionY = top + window.scrollY;36const elementX = event.pageX - elementPositionX;37const elementY = event.pageY - elementPositionY;3839newState.elementX = elementX;40newState.elementY = elementY;41newState.elementPositionX = elementPositionX;42newState.elementPositionY = elementPositionY;43}4445setState((s) => ({46...s,47...newState,48}));49};5051document.addEventListener('mousemove', handleMouseMove);5253return () => {54document.removeEventListener('mousemove', handleMouseMove);55};56}, []);5758return [state, ref];59}
Prop | Type | Default | Description |
---|---|---|---|
text | string | 'Hello!' | The text to display next to the cursor. |
color | string | '#000' | The color of the text and the dot. |
font | string | 'Arial, sans-serif' | The font of the text. |
textSize | number | 14 | The size of the text in pixels. |
gap | number | 5 | The gap between the dot and the text in pixels. |
element | HTMLElement | undefined | The HTML element where the cursor effect will be applied. If not specified, the effect applies to the document. |
size | number | 10 | The size of the dot in pixels. |