O site ta excelente, desde a ideia até a apresentação/estilização, curti demais.
Se não se importar, poderia me dizer como foi feita essa animação ao trocar de página dentro do site? 👀 Curti tanto que vou aplicar em algum projeto futuro. E quais componentes do shadcn estão sendo usados?
Parabéns pelo projeto e boa sorte na sua jornada!
Opa Ruan, obrigado!
Para a animação de troca de páginas, escolhi o gsap por conta do conrforto e o utilizei para criar as seguintes funções:
import gsap from "gsap";
import { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime";
export const animatePageIn = () => {
const bannerOne = document.getElementById("banner-1");
const bannerTwo = document.getElementById("banner-2");
const bannerThree = document.getElementById("banner-3");
const bannerFour = document.getElementById("banner-4");
if (bannerOne && bannerTwo && bannerThree && bannerFour) {
const tl = gsap.timeline();
tl.set([bannerOne, bannerTwo, bannerThree, bannerFour], {
yPercent: 0,
}).to([bannerOne, bannerTwo, bannerThree, bannerFour], {
yPercent: 100,
stagger: 0.2,
});
}
};
export const animatePageOut = (href: string, router: AppRouterInstance) => {
const bannerOne = document.getElementById("banner-1");
const bannerTwo = document.getElementById("banner-2");
const bannerThree = document.getElementById("banner-3");
const bannerFour = document.getElementById("banner-4");
if (bannerOne && bannerTwo && bannerThree && bannerFour) {
const tl = gsap.timeline();
tl.set([bannerOne, bannerTwo, bannerThree, bannerFour], {
yPercent: -100,
}).to([bannerOne, bannerTwo, bannerThree, bannerFour], {
yPercent: 0,
stagger: 0.2,
onComplete: () => {
if (href == "back") {
router.back();
} else {
router.push(href);
}
},
});
}
};
com essas funções feitas, só falta criar o esqueleto da animação, para isso criei um arquivo chamado template.tsx
no /app
do meu projeto next e inseri o seguinte conteúdo:
"use client";
import { animatePageIn } from "@/utils/animation";
import { useEffect } from "react";
export default function Template({ children }: { children: React.ReactNode }) {
useEffect(() => {
animatePageIn();
}, []);
return (
<div className="">
<div
id="banner-1"
className="min-h-screen bg-purple-500 z-[50] fixed top-0 left-0 w-[calc(25%+3px)] "
/>
<div
id="banner-2"
className="min-h-screen bg-purple-500 z-[50] fixed top-0 left-1/4 w-[calc(25%+3px)] "
/>
<div
id="banner-3"
className="min-h-screen bg-purple-500 z-[50] fixed top-0 left-2/4 w-[calc(25%+3px)] "
/>
<div
id="banner-4"
className="min-h-screen bg-purple-500 z-[50] fixed top-0 left-3/4 w-[calc(25%+3px)] "
/>
{children}
</div>
);
}
e quando eu quero trocar de páginas eu utilizo a função animatePageOut
, você tem duas opção na verdade que é utilizar ela diretamente ou criar um componente, EU gosto de fazer dessa forma: animatePageOut('/course/learn-english-89a9sd9j', router)
o router é a instância do useRouter
do "next/navigation"
, mas a outra forma é esse componente aqui ó:
"use client";
import { animatePageOut } from "@/utils/animation";
import { usePathname, useRouter } from "next/navigation";
interface Props {
href: string;
children: React.ReactNode;
className?: string;
onClick?: any;
}
export default function TransitionLink({
href,
children,
className,
onClick,
}: Props) {
const router = useRouter();
const pathname = usePathname();
const handleClick = () => {
if (pathname !== href) {
animatePageOut(href, router);
}
};
return (
<button
className={` outline-none w-fit ${className}`}
onClick={onClick ? onClick : handleClick}
>
{children}
</button>
);
}
ah, quase que esqueço da pergunta sobre o shadcn, não lembro exatamente, mas estou utilizando principalmente o Drawer
, Dialog
, Popup
, Checkbox
, Dropdown
e Select
.
Valeu Ruan!