Getting Started
Frameworks
Components
Buttons
Text Animations
Backgrounds
Device Mocks
Animated Cursor
Animated custom cursor component.
Usage
Code
import { AnimatePresence, motion, MotionValue, useMotionValue } from 'framer-motion'import React, { useEffect, useState } from 'react'import { cnBase } from 'tailwind-variants'export interface PointerProps {children: React.ReactNodeclassName?: stringname: string}export const Pointer: React.FC<PointerProps> = ({children,className,name}) => {const x = useMotionValue(0)const y = useMotionValue(0)const ref = React.useRef<HTMLDivElement>(null)const [rect, setRect] = useState<DOMRect | null>(null)const [isInside, setIsInside] = useState<boolean>(false)useEffect(() => {if (ref.current) {setRect(ref.current.getBoundingClientRect())}}, [])return (<divonMouseLeave={() => setIsInside(false)}onMouseEnter={() => setIsInside(true)}onMouseMove={(e: React.MouseEvent<HTMLDivElement>) => {if (rect) {const scrollX = window.scrollXconst scrollY = window.scrollYx.set(e.clientX - rect.left + scrollX)y.set(e.clientY - rect.top + scrollY)}}}style={{cursor: 'none'}}ref={ref}className={cnBase('relative', className)}><AnimatePresence>{isInside && <FollowPointer x={x} y={y} name={name} />}</AnimatePresence>{children}</div>)}export interface FollowPointerProps {name: stringx: MotionValue<number>;y: MotionValue<number>;}export const FollowPointer: React.FC<FollowPointerProps> = ({ x, y, name }) => {return (<><motion.divclassName="absolute z-50 h-4 w-4 rounded-full"style={{top: y,left: x,pointerEvents: 'none'}}initial={{scale: 1,opacity: 1}}animate={{scale: 1,opacity: 1}}exit={{scale: 0,opacity: 0}}><svgstroke="currentColor"fill="currentColor"strokeWidth="1"viewBox="0 0 16 16"className="h-6 w-6 -translate-x-[12px] -translate-y-[10px] -rotate-[70deg] transform stroke-sky-600 text-sky-500"height="1em"width="1em"xmlns="http://www.w3.org/2000/svg"><path d="M14.082 2.182a.5.5 0 0 1 .103.557L8.528 15.467a.5.5 0 0 1-.917-.007L5.57 10.694.803 8.652a.5.5 0 0 1-.006-.916l12.728-5.657a.5.5 0 0 1 .556.103z"></path></svg><div className="w-fit rounded-full bg-sky-500 px-2 py-1 text-white">{name || 'Tony'}</div></motion.div></>)}export interface AnimatedCursorProps {className?: string;text: string}export const AnimatedCursor: React.FC<AnimatedCursorProps> = ({ className, text }) => (<motion.divinitial={{ translateX: '0', translateY: '0' }}animate={{ translateX: ['0', '20px', '0'], translateY: ['0', '40px', '0'] }}transition={{ duration: 4, repeat: Infinity, bounce: true }}className={'relative z-[2] flex items-center gap-4'}><divclassName={cnBase('w-fit rounded-full border border-red-500 bg-red-500 px-2 py-1 text-white',className)}>{text}</div><svg fill="none" height="18" viewBox="0 0 17 18" width="17"><pathd="M15.5036 3.11002L12.5357 15.4055C12.2666 16.5204 10.7637 16.7146 10.22 15.7049L7.4763 10.6094L2.00376 8.65488C0.915938 8.26638 0.891983 6.73663 1.96711 6.31426L13.8314 1.65328C14.7729 1.28341 15.741 2.12672 15.5036 3.11002ZM7.56678 10.6417L7.56645 10.6416C7.56656 10.6416 7.56667 10.6416 7.56678 10.6417L7.65087 10.4062L7.56678 10.6417Z"fill="#f31260"stroke="#f31260"strokeWidth="1.5"/></svg></motion.div>)
Props
Attribute | Type | Description | Default |
---|---|---|---|
className | string | The class name to be applied to the component. | undefined |
children | ReactNode | The content to be displayed inside the button. | undefined |
On this page