A download button whose Apple icon slides out and an arrow slides in on hover for a playful call to action.
"use client";
import { buttonVariants } from "@/components/ui/button";
import { ArrowRight } from "lucide-react";
import { motion, Transition } from "motion/react";
import { HTMLAttributes, useState } from "react";
type IconProps = HTMLAttributes<SVGElement>;
const AppleIcon = (props: IconProps) => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="209"
height="256"
viewBox="0 0 814 1000"
{...props}
>
<path d="M788.1 340.9c-5.8 4.5-108.2 62.2-108.2 190.5 0 148.4 130.3 200.9 134.2 202.2-.6 3.2-20.7 71.9-68.7 141.9-42.8 61.6-87.5 123.1-155.5 123.1s-85.5-39.5-164-39.5c-76.5 0-103.7 40.8-165.9 40.8s-105.6-57-155.5-127C46.7 790.7 0 663 0 541.8c0-194.4 126.4-297.5 250.8-297.5 66.1 0 121.2 43.4 162.7 43.4 39.5 0 101.1-46 176.3-46 28.5 0 130.9 2.6 198.3 99.2zm-234-181.5c31.1-36.9 53.1-88.1 53.1-139.3 0-7.1-.6-14.3-1.9-20.1-50.6 1.9-110.8 33.7-147.1 75.8-28.5 32.4-55.1 83.6-55.1 135.5 0 7.8 1.3 15.6 1.9 18.1 3.2.6 8.4 1.3 13.6 1.3 45.4 0 102.5-30.4 135.5-71.3z" />
</svg>
);
const TRANSITION: Transition = { duration: 0.5, ease: "easeInOut" };
const JoiDownloadButton = () => {
const [hovered, setHovered] = useState(false);
const handleToggleMouseState = () => setHovered((prev) => !prev);
return (
<div className="flex items-center justify-center size-full bg-background rounded-xl">
<motion.button
className={buttonVariants({
className: "overflow-hidden flex items-center gap-2 relative",
})}
onMouseEnter={handleToggleMouseState}
onMouseLeave={handleToggleMouseState}
>
<motion.span
animate={{ x: hovered ? "-200%" : 0 }}
transition={TRANSITION}
>
<AppleIcon className="size-5 fill-primary-foreground" />
</motion.span>
<motion.span animate={{ x: hovered ? -22 : 0 }} transition={TRANSITION}>
Download for IOS
</motion.span>
<motion.span
animate={{ x: hovered ? -12 : 20, opacity: hovered ? 1 : 0 }}
transition={TRANSITION}
className="absolute right-0 top-0 bottom-0 my-auto size-5 flex items-center justify-center"
>
<ArrowRight className="size-5" />
</motion.span>
</motion.button>
</div>
);
};
export default JoiDownloadButton;