Skip to content

Commit

Permalink
refactored approach to single Transition wrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
rijk committed Mar 8, 2024
1 parent 9444001 commit e8505d2
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 89 deletions.
9 changes: 4 additions & 5 deletions app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
import Nav from "@/components/nav";
import Transitions from "@/components/page-transitions/context";
import Animate from "@/components/page-transitions/animate";
import Transitions, { Animate } from "@/components/transitions";

const inter = Inter({ subsets: ["latin"] });

Expand All @@ -19,10 +18,10 @@ export default function RootLayout({
}>) {
return (
<html lang="en" className="h-full">
<body className={`${inter.className} bg-slate-400 flex flex-col h-full`}>
<Transitions>
<body className={`${inter.className} bg-slate-400 h-full`}>
<Transitions className="h-full flex flex-col ">
<Nav />
<Animate>{children}</Animate>
<Animate className="flex-1">{children}</Animate>
</Transitions>
<a
className="absolute bottom-10 right-10 bg-white px-4 py-2 shadow-sm transition-all duration-500 rounded-lg hover:shadow-lg flex items-center gap-2"
Expand Down
23 changes: 0 additions & 23 deletions components/link.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion components/nav.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Link from "./link";
import Link from "next/link";

export default function Nav() {
return (
Expand Down
24 changes: 0 additions & 24 deletions components/page-transitions/animate.tsx

This file was deleted.

36 changes: 0 additions & 36 deletions components/page-transitions/context.tsx

This file was deleted.

87 changes: 87 additions & 0 deletions components/transitions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
"use client";

import { AnimatePresence, motion } from "framer-motion";
import { useRouter } from "next/navigation";
import {
createContext,
MouseEventHandler,
PropsWithChildren,
use,
useTransition,
} from "react";

export const DELAY = 1000;

const sleep = (ms: number) =>
new Promise<void>((resolve) => setTimeout(() => resolve(), ms));
const noop = () => {};

type TransitionContext = {
pending: boolean;
navigate: (url: string) => void;
};
const Context = createContext<TransitionContext>({
pending: false,
navigate: noop,
});
export const usePageTransition = () => use(Context);
export const usePageTransitionHandler = () => {
const { navigate } = usePageTransition();
const onClick: MouseEventHandler<HTMLAnchorElement> = (e) => {
e.preventDefault();
const href = e.currentTarget.getAttribute("href");
if (href) navigate(href);
};

return onClick;
};

type Props = PropsWithChildren<{
className?: string;
}>;

export default function Transitions({ children, className }: Props) {
const [pending, start] = useTransition();
const router = useRouter();
const navigate = (href: string) => {
start(async () => {
router.push(href);
await sleep(DELAY);
});
};

const onClick: MouseEventHandler<HTMLDivElement> = (e) => {
const a = (e.target as Element).closest("a");
if (a) {
e.preventDefault();
const href = a.getAttribute("href");
if (href) navigate(href);
}
};

return (
<Context.Provider value={{ pending, navigate }}>
<div onClickCapture={onClick} className={className}>
{children}
</div>
</Context.Provider>
);
}

export function Animate({ children, className }: Props) {
const { pending } = usePageTransition();
return (
<AnimatePresence>
{!pending && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className={className}
>
{children}
</motion.div>
)}
</AnimatePresence>
);
}

0 comments on commit e8505d2

Please sign in to comment.