Docs
Logo Origami
A logo origami effect is a design technique where a logo appears to fold, unfold, or transform like origami, adding a dynamic and creative visual appeal.
Installation
Install dependencies
npm install framer-motion lucide-react
Run the following command
It will create a new file logo-origami.tsx
inside the components/mage-ui/icon
directory.
mkdir -p components/mage-ui/icon && touch components/mage-ui/icon/logo-origami.tsx
Paste the code
Open the newly created file and paste the following code:
"use client";
import React, { ReactElement, useEffect, useRef, useState } from "react";
import { AnimatePresence, motion } from "framer-motion";
import { SiAmazon, SiGithub, SiGoogle, SiMeta, SiTwitch } from "react-icons/si";
import { twMerge } from "tailwind-merge";
export const DivOrigami = () => {
return (
<section className="flex h-full w-[90vw] flex-col items-center justify-center gap-12 bg-neutral-950 px-4 py-24 md:flex-row">
<LogoRolodex
items={[
<LogoItem key={1} className="bg-orange-300 text-neutral-900">
<SiAmazon />
</LogoItem>,
<LogoItem key={2} className="bg-green-300 text-neutral-900">
<SiGoogle />
</LogoItem>,
<LogoItem key={3} className="bg-blue-300 text-neutral-900">
<SiMeta />
</LogoItem>,
<LogoItem key={4} className="bg-white text-black">
<SiGithub />
</LogoItem>,
<LogoItem key={5} className="bg-purple-300 text-neutral-900">
<SiTwitch />
</LogoItem>,
]}
/>
</section>
);
};
const DELAY_IN_MS = 2500;
const TRANSITION_DURATION_IN_SECS = 1.5;
const LogoRolodex = ({ items }: { items: ReactElement[] }) => {
const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
const [index, setIndex] = useState(0);
useEffect(() => {
intervalRef.current = setInterval(() => {
setIndex((pv) => pv + 1);
}, DELAY_IN_MS);
return () => {
clearInterval(intervalRef.current || undefined);
};
}, []);
return (
<div
style={{
transform: "rotateY(-20deg)",
transformStyle: "preserve-3d",
}}
className="relative z-0 h-44 w-60 shrink-0 rounded-xl border border-neutral-700 bg-neutral-800"
>
<AnimatePresence mode="sync">
<motion.div
style={{
y: "-50%",
x: "-50%",
clipPath: "polygon(0 0, 100% 0, 100% 50%, 0 50%)",
zIndex: -index,
backfaceVisibility: "hidden",
}}
key={index}
transition={{
duration: TRANSITION_DURATION_IN_SECS,
ease: "easeInOut",
}}
initial={{ rotateX: "0deg" }}
animate={{ rotateX: "0deg" }}
exit={{ rotateX: "-180deg" }}
className="absolute left-1/2 top-1/2"
>
{items[index % items.length]}
</motion.div>
<motion.div
style={{
y: "-50%",
x: "-50%",
clipPath: "polygon(0 50%, 100% 50%, 100% 100%, 0 100%)",
zIndex: index,
backfaceVisibility: "hidden",
}}
key={(index + 1) * 2}
initial={{ rotateX: "180deg" }}
animate={{ rotateX: "0deg" }}
exit={{ rotateX: "0deg" }}
transition={{
duration: TRANSITION_DURATION_IN_SECS,
ease: "easeInOut",
}}
className="absolute left-1/2 top-1/2"
>
{items[index % items.length]}
</motion.div>
</AnimatePresence>
<hr
style={{
transform: "translateZ(1px)",
}}
className="absolute left-0 right-0 top-1/2 z-[999999999] -translate-y-1/2 border-t-2 border-neutral-800"
/>
</div>
);
};
const LogoItem = ({
children,
className,
}: {
children: React.ReactNode;
className?: string;
}) => {
return (
<div
className={twMerge(
"grid h-36 w-52 place-content-center rounded-lg bg-neutral-700 text-6xl text-neutral-50",
className
)}
>
{children}
</div>
);
};