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>
  );
};