🎉 We just launched our Bento Grid Maker! ✨ Create beautiful grid layouts with our interactive builder! 🚀

FAQ Bento Grid

What are the premium models?
Why isn't Cursor completely free?
What are fast and slow uses?
What code do you store?
Who owns the code generated in Cursor?
How do the plan limits work?
Do all Cursor features work with an API key?
What is Cursor Tab?
Where can I ask more questions?

Install dependencies

npm i framer-motion lucide-react @radix-ui/react-slot

Add components

npx shadcn-ui@latest add card button

Add utils

// Create utils/cn.ts
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}

Add custom cursor component

"use client"

import { useEffect, useState } from "react"
import { motion, AnimatePresence } from "framer-motion"

export function FunnyCursor() {
  const [position, setPosition] = useState({ x: 0, y: 0 })
  const [isVisible, setIsVisible] = useState(false)
  const [isClicked, setIsClicked] = useState(false)

  useEffect(() => {
    const updatePosition = (e: MouseEvent) => {
      setPosition({ x: e.clientX, y: e.clientY })
      setIsVisible(true)
    }

    const handleMouseDown = () => setIsClicked(true)
    const handleMouseUp = () => setIsClicked(false)

    window.addEventListener("mousemove", updatePosition)
    window.addEventListener("mouseleave", () => setIsVisible(false))
    window.addEventListener("mouseenter", () => setIsVisible(true))
    window.addEventListener("mousedown", handleMouseDown)
    window.addEventListener("mouseup", handleMouseUp)

    return () => {
      window.removeEventListener("mousemove", updatePosition)
      window.removeEventListener("mouseleave", () => setIsVisible(false))
      window.removeEventListener("mouseenter", () => setIsVisible(true))
      window.removeEventListener("mousedown", handleMouseDown)
      window.removeEventListener("mouseup", handleMouseUp)
    }
  }, [])

  return (
    <AnimatePresence>
      {isVisible && (
        <motion.div
          className="pointer-events-none fixed left-0 top-0 z-50 h-12 w-12 text-white mix-blend-difference"
          animate={{
            x: position.x - 24,
            y: position.y - 24,
            scale: isClicked ? 0.8 : 1,
            rotate: isClicked ? 45 : 0,
          }}
          exit={{
            opacity: 0,
            scale: 0.5,
          }}
          transition={{
            type: "spring",
            stiffness: 300,
            damping: 20,
            mass: 0.5,
          }}
        >
          <motion.svg
            xmlns="http://www.w3.org/2000/svg"
            viewBox="0 0 24 24"
            fill="currentColor"
            animate={{
              rotate: isClicked ? 360 : 0,
            }}
            transition={{
              type: "spring",
              stiffness: 260,
              damping: 20,
            }}
          >
            <path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm3.59-13L12 10.59 8.41 7 7 8.41 10.59 12 7 15.59 8.41 17 12 13.41 15.59 17 17 15.59 13.41 12 17 8.41z" />
          </motion.svg>
          <motion.div
            className="absolute left-1/2 top-1/2 h-2 w-2 -translate-x-1/2 -translate-y-1/2 rounded-full bg-white"
            animate={{
              scale: [1, 1.5, 1],
            }}
            transition={{
              repeat: Infinity,
              duration: 1,
              ease: "easeInOut",
            }}
          />
        </motion.div>
      )}
    </AnimatePresence>
  )
}