refactor: modularize envelope reveal and logo components for easier usage across the site

This commit is contained in:
ramvignesh-b
2026-04-26 00:55:19 +05:30
parent f352c298e7
commit dadb688c50
4 changed files with 147 additions and 151 deletions
+10 -10
View File
@@ -1,26 +1,26 @@
import { DotIcon } from "@phosphor-icons/react";
import "@fontsource/knewave/400.css";
export default function Logo() {
export default function Logo({ scale = 2 }) {
return (
<span
<div
role="img"
aria-label="Pi Ku"
className="inline-flex items-baseline justify-center leading-none select-none"
style={{ fontFamily: "'Knewave', serif" }}
style={{ fontFamily: "'Knewave', serif", scale }}
>
<span className="text-2xl font-light text-accent">&nbsp;Pi</span>
<span className={`text-xl font-light text-accent`}>&nbsp;Pi</span>
<DotIcon
weight="fill"
size={12}
className="text-accent translate-y-[0.3em] -mx-px"
size={6}
className={`text-primary translate-y-1 -mx-px`}
/>
<span className="text-2xl font-light text-accent">&nbsp;Ku</span>
<span className={`text-xl font-light text-accent`}>&nbsp;Ku</span>
<DotIcon
weight="fill"
size={12}
className="text-accent translate-y-[0.3em] -mx-px"
size={6}
className={`text-primary translate-y-1 -mx-px`}
/>
</span>
</div>
);
}
@@ -8,6 +8,7 @@ export interface EnvelopeRevealProps {
date?: string;
onRevealComplete: () => void;
ignite: boolean;
isFlip?: boolean;
}
export function EnvelopeReveal({
@@ -15,9 +16,14 @@ export function EnvelopeReveal({
date,
onRevealComplete,
ignite,
isFlip,
}: EnvelopeRevealProps) {
const [revealLetter, setRevealLetter] = useState(false);
const [isFlipped, setIsFlipped] = useState(false);
const [isFlipped, setIsFlipped] = useState(!!isFlip);
useEffect(() => {
setIsFlipped(!!isFlip);
}, [isFlip]);
const [burn, setBurn] = useState<{ width: number; height: number }>({
width: 0,
@@ -27,7 +33,10 @@ export function EnvelopeReveal({
const flapCheckbox = useRef<HTMLInputElement>(null);
useEffect(() => {
if (!ignite) return;
if (!ignite) {
setBurn({ width: 0, height: 0 });
return;
}
const burnInterval = setInterval(() => {
setBurn((prev) => ({ width: prev.width + 4, height: prev.height + 6 }));
}, 100);
@@ -43,90 +52,86 @@ export function EnvelopeReveal({
};
return (
<div className="h-screen mx-auto flex-col items-center flex justify-center">
<div className="perspective-distant scale-80 duration-1000 transition-all animate-[pulse_2s_linear_1]">
<>
<div
className={`relative h-70 w-105 transform-3d transition-transform duration-2000 ${isFlipped ? "rotate-y-180" : ""}`}
>
<div
className={`relative h-70 w-105 transform-3d transition-transform duration-2000 ${isFlipped ? "rotate-y-180" : ""}`}
className={` flex backface-hidden rotate-y-180 justify-center transition-all duration-1000 ${isFlipped ? "" : "pointer-events-none"}`}
>
<div
className={` flex backface-hidden rotate-y-180 justify-center transition-all duration-1000 ${isFlipped ? "" : "pointer-events-none"}`}
id="env-top"
className="z-4 delay-500 transition-all duration-2000 absolute peer h-40 w-54 mt-0 bg-base-200 mask mask-triangle-2 scale-x-234 has-checked:scale-y-[-1] has-checked:-translate-y-full has-checked:z-1 has-checked:duration-1000"
>
<div
id="env-top"
className="z-4 delay-500 transition-all duration-2000 absolute peer h-40 w-54 mt-0 bg-base-200 mask mask-triangle-2 scale-x-234 has-checked:scale-y-[-1] has-checked:-translate-y-full has-checked:z-1 has-checked:duration-1000"
>
<input
type="checkbox"
className="transition checkbox absolute h-full w-full text-transparent bg-transparent z-100"
ref={flapCheckbox}
/>
</div>
<img
className={
"translate-y-24 delay-2000 absolute z-6 peer-has-checked:pointer-events-none peer-has-checked:opacity-0 peer-has-checked:delay-0 transition-opacity duration-1000 cursor-pointer"
}
src={waxSeal}
alt="Seal"
onClick={() => flapCheckbox.current?.click()}
onKeyDown={() => flapCheckbox.current?.click()}
<input
type="checkbox"
className="transition checkbox absolute h-full w-full text-transparent bg-transparent z-100"
ref={flapCheckbox}
/>
<button
type="button"
id="letter"
className={`absolute mx-auto transition-all peer-has-checked:delay-800 peer-has-checked:duration-1000 duration-1000 mt-2 h-55 w-105 bg-paper peer-has-checked:-mt-12 hover:-mt-24 cursor-pointer ${revealLetter ? "duration-1000 peer-has-checked:duration-3000 w-screen max-w-4xl h-screen z-101 -translate-y-90" : "peer-has-checked:z-1"}`}
onClick={handleClick}
></button>
<div
id="env-right"
className="absolute h-70 w-105 bg-base-300 mask mask-triangle-3 -mr-48 z-3 pointer-events-none"
></div>
<div
id="env-left"
className="absolute h-70 w-105 bg-base-300 mask mask-triangle-4 -ml-48 z-3 pointer-events-none"
></div>
<button
type="button"
id="env-bottom"
className="absolute h-70 w-45 bg-base-200 mask mask-triangle-2 scale-y-[-1] mt-15 scale-x-240 z-3"
></button>
</div>
<img
className={
"translate-y-24 delay-2000 absolute z-6 peer-has-checked:pointer-events-none peer-has-checked:opacity-0 peer-has-checked:delay-0 transition-opacity duration-1000 cursor-pointer"
}
src={waxSeal}
alt="Seal"
onClick={() => flapCheckbox.current?.click()}
onKeyDown={() => flapCheckbox.current?.click()}
/>
<button
id="env-front"
type="button"
className={`text-left p-10 absolute inset-0 backface-hidden w-110 bg-base-200 z-99 rounded-md -translate-x-2 ${isFlipped ? "pointer-events-none" : ""}`}
onClick={() => setIsFlipped((prev) => !prev)}
>
<span className={"text-neutral-content/60 font-xs font-display"}>
to
</span>
<h1 className="text-3xl font-bold text-base-content">
{recipient}
</h1>
<p className="text-base-content/60 font-display mt-8">{date}</p>
<img
src={stamp}
alt={"stamp"}
className={
"z-0 rotate-6 opacity-80 text-accent absolute mt-0 mr-1 top-4 right-0"
}
/>
<WavesIcon
className={"absolute mt-0 mr-12 top-18 right-8 text-primary"}
size={50}
/>
<WavesIcon
className={"absolute mt-0 mr-4 top-18 right-8 text-primary"}
size={50}
/>
</button>
id="letter"
className={`absolute mx-auto transition-all peer-has-checked:delay-800 peer-has-checked:duration-1000 duration-1000 mt-2 h-55 w-105 bg-paper peer-has-checked:-mt-12 hover:-mt-24 cursor-pointer ${revealLetter ? "duration-1000 peer-has-checked:duration-3000 w-screen max-w-4xl h-screen z-101 -translate-y-90" : "peer-has-checked:z-1"}`}
onClick={handleClick}
></button>
<div
id="env-right"
className="absolute h-70 w-105 bg-base-300 mask mask-triangle-3 -mr-48 z-3 pointer-events-none"
></div>
<div
id="env-left"
className="absolute h-70 w-105 bg-base-300 mask mask-triangle-4 -ml-48 z-3 pointer-events-none"
></div>
<button
type="button"
id="env-bottom"
className="absolute h-70 w-45 bg-base-200 mask mask-triangle-2 scale-y-[-1] mt-15 scale-x-240 z-3"
></button>
</div>
<button
id="env-front"
type="button"
className={`text-left p-10 absolute inset-0 backface-hidden w-110 bg-base-200 z-99 rounded-md -translate-x-2 ${isFlipped ? "pointer-events-none" : ""}`}
onClick={() => setIsFlipped((prev) => !prev)}
>
<span className={"text-neutral-content/60 font-xs font-display"}>
to
</span>
<h1 className="text-3xl font-bold text-base-content">{recipient}</h1>
<p className="text-base-content/60 font-display mt-8">{date}</p>
<img
src={stamp}
alt={"stamp"}
className={
"z-0 rotate-6 opacity-80 text-accent absolute mt-0 mr-1 top-4 right-0"
}
/>
<WavesIcon
className={"absolute mt-0 mr-12 top-18 right-8 text-primary"}
size={50}
/>
<WavesIcon
className={"absolute mt-0 mr-4 top-18 right-8 text-primary"}
size={50}
/>
</button>
</div>
{ignite && (
<div className="absolute w-90 h-60 bg-transparent z-100 overflow-hidden flex align-baseline">
<div className="absolute w-115 h-70 z-100 overflow-hidden flex align-baseline -translate-y-70 -translate-x-5">
<div
className="absolute border-2 border-amber-200 -bottom-3 -right-3 w-0 h-0 transition-all duration-500 bg-base-100 rounded-tl-full rounded-bl-full origin-bottom-right"
className="absolute z-1000 border-2 border-amber-200 -bottom-3 -right-3 w-0 h-0 transition-all duration-500 bg-base-100 rounded-tl-full rounded-bl-full origin-bottom-right"
style={{
width: 2 * burn.width,
height: 2 * burn.height,
@@ -134,6 +139,6 @@ export function EnvelopeReveal({
></div>
</div>
)}
</div>
</>
);
}