Skip to content

Instantly share code, notes, and snippets.

@divv919
Created November 29, 2025 10:39
Show Gist options
  • Select an option

  • Save divv919/ba02a60be29b275f1a9c342024112cf1 to your computer and use it in GitHub Desktop.

Select an option

Save divv919/ba02a60be29b275f1a9c342024112cf1 to your computer and use it in GitHub Desktop.
"use client";
import { easeInOut, motion, Transition, Variants } from "motion/react";
export default function FinalComponent() {
return (
<motion.div
variants={containerVariants}
initial="close"
animate="close"
whileHover="open"
className="h-150 rounded-lg w-130 bg-linear-180 from-[#303034] to-[#2a2a2f] backdrop-blur-lg shadow-[inset_0px_2px_1px_rgba(255,255,255,0.05),_0px_8px_12px_rgba(0,0,0,0.1)] relative flex flex-col gap-8"
>
<MacBook />
<Details />
<div className="absolute h-full w-full bg-radial from-transparent to-black/10 pointer-events-none"></div>
</motion.div>
);
}
const hoverDetails = [
{
title: "Device",
content: "MacBook Pro",
},
{
title: "Browser",
content: "Chrome",
},
{
title: "Location",
content: "San Fransisco, CA",
},
];
const Details = () => {
return (
<div className=" h-full my-10 text-gray-300/80 flex flex-col gap-7">
<div className="flex flex-col gap-4 divide-y-[2px] divide-laptop-body-dark/50">
{hoverDetails.map((d, index) => {
return (
<div key={d.title} className=" relative h-9 w-[70%] mx-auto ">
<motion.div
variants={titleVariant}
className="absolute flex w-fit "
transition={{
delay: (index + 1) * 0.05,
duration: 0.6,
ease: [0.86, -0.01, 0.48, 1],
}}
>
<motion.span className="" layoutId={"title-" + d.title}>
{d.title}
</motion.span>
</motion.div>
<motion.div
custom={index}
variants={contentVariant}
className="absolute w-full text-center text-gray-200 font-medium"
>
{d.content}
</motion.div>
</div>
);
})}
</div>
<motion.div
// variants={buttonVariant}
className="w-full flex justify-center "
>
<motion.button
variants={buttonVariant}
className="font-medium border-[2px] w-[70%] py-2 rounded-md "
>
Sign out device
</motion.button>
</motion.div>
</div>
);
};
const MacBook = () => {
return (
<motion.div
variants={macBookVariants}
style={{
perspective: "1500px",
transformStyle: "preserve-3d",
backfaceVisibility: "hidden",
}}
className="flex justify-center items-end w-full h-[70%] "
>
<Screen />
<LowerBody />
</motion.div>
);
};
const LowerBody = () => {
return (
<div
style={{
transform: "translateZ(30px)",
}}
className=" w-87 h-5 bg-linear-0 from-laptop-body-dark to-laptop-body-light rounded-b-2xl rounded-t-[5px] relative border-t-3 border-laptop-body-border "
>
<div className="absolute -translate-y-[32%] h-[8px] w-11 bg-neutral-700 shadow-[inset_0px_-0.5px_3px_rgba(0,0,0,0.35)] rounded-b-xl border-b-2 border-laptop-body-border right-1/2 translate-x-1/2 "></div>
</div>
);
};
const Screen = () => {
return (
<motion.div
variants={ScreenVariant}
style={{
backfaceVisibility: "hidden",
transformOrigin: "50% 100%",
transformStyle: "preserve-3d",
perspective: "1000px",
}}
className="w-75 h-40 rounded-md opacity-100 bg-linear-0 from-neutral-900 to-neutral-700 z-100 outline-2 border-4 border-neutral-900 absolute -translate-y-[8%] "
>
<motion.div
style={{
rotateX: "120deg",
}}
variants={lightVariant}
className="z-100 w-[100%] absolute translate-x-[0px] -translate-y-[125px] translate-z-[75px] bg-linear-0 from-transparent to-white/10 blur h-40 "
></motion.div>
<motion.div
style={{
rotateX: "110deg",
}}
className="w-[104%] absolute -translate-x-[6px] rounded-t-xl -translate-y-[7px] translate-z-[1px] bg-laptop-body-light h-2 "
></motion.div>
<motion.div
variants={screenContentVariant}
className="overflow-hidden opacity-0 w-full h-full bg-linear-90 from-neutral-800 to-neutral-900 relative"
>
<div className=" size-50 h-100 z-100 bg-linear-0 from-neutral-500/0 to-neutral-500/40 rotate-45 top-0 -translate-y-1/2 -translate-x-[10%] absolute"></div>
<div className="absolute z-10 size-15 top-1/2 -translate-y-1/2 left-1/2 -translate-x-1/2 rounded-full bg-neutral-900 border-b-2 border-neutral-700 flex items-center justify-center ">
<div className="size-4 rounded-full bg-teal-200 relative z-1000">
<div className="size-4 rounded-full bg-teal-300 absolute blur-sm z-1000"></div>
</div>
</div>
</motion.div>
</motion.div>
);
};
// VARIANTS
const commonTransition: Transition = {
duration: 0.6,
ease: easeInOut,
};
const containerVariants: Variants = {
open: {},
close: {},
};
const macBookVariants: Variants = {
open: {},
close: {},
};
const ScreenVariant: Variants = {
open: {
rotateX: "16deg",
transition: {
ease: [1, -0.01, 0.35, 1],
duration: 0.7,
},
},
close: {
rotateX: "-60deg",
transition: {
ease: [1, -0.01, 0.35, 1],
duration: 0.7,
},
},
};
const screenContentVariant: Variants = {
open: {
opacity: 1,
transition: commonTransition,
},
close: {
opacity: 0,
transition: commonTransition,
},
};
const lightVariant: Variants = {
open: {
opacity: 0,
transition: {
ease: [1, -0.01, 0.35, 1],
duration: 0.7,
},
},
close: {
opacity: 1,
transition: {
ease: [1, -0.01, 0.35, 1],
duration: 0.7,
},
},
};
const buttonVariant: Variants = {
open: {
opacity: 1,
borderColor: "rgba(94, 95, 110, 0.4)",
transition: commonTransition,
color: "rgb(229, 231, 235)",
},
close: {
opacity: 1,
borderColor: "rgba(94, 95, 110, 0.09)",
transition: commonTransition,
color: "rgba(156, 163, 175, 0.5)",
},
};
const titleVariant: Variants = {
open: {
left: 0,
translateX: "0%",
},
close: { left: "50%", translateX: "-50%" },
};
const contentVariant: Variants = {
open: (index: number) => ({
opacity: 1,
filter: "blur(0px)",
transition: {
duration: 0.4,
delay: 0.4 + index * 0.05,
},
}),
close: (index: number) => ({
opacity: 0,
filter: "blur(10px)",
transition: {
duration: 0.3,
delay: index * 0.05,
},
}),
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment