Quickie

A boucy, fluid, speedy & hoverable component for displaying links or socials.

Try hovering over the links:)

Code

npm i framer-motion react-icons
/components/lab/Quickie/quickie.js
"use client";
import React, { useState,useRef } from "react";
import {AiOutlineMenu,AiOutlineClose} from "react-icons/ai"
import { motion,useMotionValue,useSpring,useTransform, } from "framer-motion";
const Quickie = () => {
const [open, setOpen] = useState(false)
let mouseX = useMotionValue(Infinity);
const meun = ["Peek","Timemachine","Cmdkbox","Card"]
const socials = ["X","Github"]
return (
<div className="w-full h-full flex justify-center items-center">
<motion.div whileHover={open && {scale:1.3,transition:{duration:0.2}}} className="z-10">{!open ? <AiOutlineMenu onClick={() => setOpen(!open)} /> : <AiOutlineClose onClick={() => setOpen(!open)} />}</motion.div>
{open && <motion.div animate={{opacity:[0,0.8],transition:{duration:0.2}}} className="fixed m-0 bottom-0 w-screen h-full bg-[#f1f1f1]" />}
{open &&
<motion.div animate={{y:-100,height:[50,50,100,150,180,150],transition:{type:"spring",stiffness:120,duration:0.4}}} className="z-10 flex gap-6 absolute mr-[110px]">
<motion.div onMouseMove={(e) => mouseX.set(e.pageY)} onMouseLeave={() => mouseX.set(Infinity)} >
{meun.map((item) => (
<Item mouseX={mouseX} text={item} />
))}
</motion.div>
<div className="w-[32px] rounded-[15px] bg-white">
{Array(meun.length).fill(0).map((item, index) => (
<motion.div whileHover={{scale:1.3,transition:{duration:0.2}}} className="bg-gray-500 mt-6 m-auto w-2 rounded-full h-2" />
))}
</div>
</motion.div>}
{open &&
<motion.div animate={{y:70,height:[50,60,80,100,90],transition:{type:"spring",stiffness:120,duration:0.4}}} className="z-10 flex gap-6 absolute mr-[70px]">
<motion.div onMouseMove={(e) => mouseX.set(e.pageY)} onMouseLeave={() => mouseX.set(Infinity)} >
{socials.map((item) => (
<Item mouseX={mouseX} text={item} />
))}
</motion.div>
<div className="w-[32px] rounded-[15px] bg-white">
{Array(socials.length).fill(0).map((item, index) => (
<motion.div whileHover={{scale:1.3,transition:{duration:0.2}}} className="bg-gray-500 mt-6 m-auto w-2 rounded-full h-2" />
))}
</div>
</motion.div>}
</div>
)
}
const Item = ({ mouseX, text }) => {
let refLol = useRef(null);
let distance = useTransform(mouseX, (val) => {
let bounds = refLol.current?.getBoundingClientRect() ?? { y: 0, height: 0 };
return val - bounds.y - bounds.height / 2 ;
});
let widthSync = useTransform(distance, [-50, 0, 50], [1, 1.25, 1]);
let scale = useSpring(widthSync, { mass: 0.1, stiffness: 150, damping: 10 });
return (
<motion.div ref={refLol} style={{ scale}} className="cursor-pointer right-[50px] mt-4 text-xs uppercase text-gray-500 text-right">
{text}
</motion.div>
);
}
export default Quickie;

The code for this component is here. Some libraries used are:

  • Next.js
  • framer-motion
  • tailwindcss
  • react-icons