Created
November 29, 2025 10:39
-
-
Save divv919/ba02a60be29b275f1a9c342024112cf1 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| "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