<div id="root" class="panel center"></div>
.app {
  padding: 10px;
}

.circle {
  position: fixed;
  transform: translate(-50%, -50%);
  top: 0;
  left: 0;
  opacity: 0.3;
}

.circle.sm {
  width: 30px;
  height: 30px;
}

.circle.md {
  width: 60px;
  height: 60px;
}

.circle.lg {
  width: 90px;
  height: 90px;
}
const { useEffect, useRef, useState, useImperativeHandle, forwardRef } = React;

const Circle = forwardRef(({ size, delay }, ref) => {
  const el = useRef();
    
  useImperativeHandle(ref, () => {           
    
    // return our API
    return {
      moveTo(x, y) {
        gsap.to(el.current, { x, y, delay });
      }
    };
  }, [delay]);
  
  return <div className={`circle ${size}`} ref={el}></div>;
});

function App() {    
  const circleRefs = useRef([]);
  
  // reset on re-renders
  circleRefs.current = [];
     
  useEffect(() => {
    
    circleRefs.current.forEach(ref => ref.moveTo(innerWidth / 2, innerHeight / 2));
    
    const onMove = ({ clientX, clientY }) => {      
      circleRefs.current.forEach(ref => ref.moveTo(clientX, clientY));
    };
    
    window.addEventListener("pointermove", onMove);
    
    return () => window.removeEventListener("pointermove", onMove);
  }, []);
  
  const addCircleRef = ref => {
    if (ref) {
      circleRefs.current.push(ref);
    }    
  };
  
  return (
    <div className="app">   
      <p>Move your mouse around</p>
      <Circle size="sm" ref={addCircleRef} delay={0} />
      <Circle size="md" ref={addCircleRef} delay={0.1} />
      <Circle size="lg" ref={addCircleRef} delay={0.2} />
    </div>
  );
}

ReactDOM.render(<App />, document.querySelector("#root"));
View Compiled

External CSS

  1. https://codepen.io/GreenSock/pen/gOWxmWG.css

External JavaScript

  1. https://unpkg.co/gsap@3/dist/gsap.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js
  3. https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js