Skip to content

Commit

Permalink
Add loading state and direct linking to projects
Browse files Browse the repository at this point in the history
  • Loading branch information
anish-shanbhag committed May 12, 2024
1 parent c62e1ac commit 4409ac9
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 9 deletions.
40 changes: 34 additions & 6 deletions app/components/BlurOverlay.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,46 @@
"use client";

import { useAtomValue } from "jotai";
import { useEffect, useState } from "react";

import { activeProjectAtom } from "../utils/state";
import { activeProjectAtom, isLoadingAtom } from "../utils/state";
import { OPEN_ANIMATION_DURATION_CLASS } from "../utils/constants";

export default function BlurOverlay() {
const isLoading = useAtomValue(isLoadingAtom);
const activeProject = useAtomValue(activeProjectAtom);
const [inFront, setInFront] = useState(true);

useEffect(() => {
if (!isLoading) {
setTimeout(() => setInFront(false), 500);
}
}, [isLoading]);

return (
<div
className={`fixed top-0 w-screen h-screen transition ${OPEN_ANIMATION_DURATION_CLASS} ${
activeProject !== null ? "opacity-100 z-[900]" : "opacity-0"
} backdrop-blur-sm`}
/>
<>
<div
className={`fixed top-0 w-screen h-screen transition ${OPEN_ANIMATION_DURATION_CLASS} ${
isLoading || activeProject !== null
? "opacity-100 z-[900]"
: "opacity-0"
} ${isLoading ? "backdrop-blur-lg" : "backdrop-blur-sm"} ${
inFront ? "z-[900]" : ""
}`}
>
<div
className={`absolute transition-all ${OPEN_ANIMATION_DURATION_CLASS} ${
isLoading ? "top-0 opacity-100" : "top-[60vh] opacity-0"
}`}
>
<div className="flex items-center justify-center w-screen h-screen">
<div className="flex justify-center items-center w-32 h-32 bg-white border-white border-8 shadow-2xl rounded-lg">
<div className="absolute w-16 h-16 rounded-full border-8 border-blue-500" />
<div className="w-16 h-16 border-r-8 border-t-8 border-teal-400 rounded-full z-[10] animate-spin" />
</div>
</div>
</div>
</div>
</>
);
}
6 changes: 6 additions & 0 deletions app/components/GradientMask.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
import { ReactNode, useLayoutEffect, useRef } from "react";
import { Noise } from "noisejs";
import { useInView } from "react-intersection-observer";
import { useSetAtom } from "jotai";

import { isLoadingAtom } from "../utils/state";

// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const noise = new Noise(Math.random());
Expand Down Expand Up @@ -37,9 +40,12 @@ export default function GradientMask({
const { ref, inView } = useInView();
inViewRef.current = inView;

const setIsLoading = useSetAtom(isLoadingAtom);

useLayoutEffect(() => {
if (didSetupAnimation.current) return;
didSetupAnimation.current = true;
setIsLoading(false);

const ctx = canvas.current!.getContext("2d")!;

Expand Down
16 changes: 15 additions & 1 deletion app/components/Transitioner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

import { useAtom, useSetAtom } from "jotai";
import { useEffect, useRef, useState } from "react";
import { usePathname } from "next/navigation";

import { activeProjectAtom, isTransitioningAtom } from "../utils/state";
import { OPEN_ANIMATION_DURATION } from "../utils/constants";
import { Project } from "../utils/projects";
import { Project, projects } from "../utils/projects";

function useScrollbarWidth() {
const didCompute = useRef(false);
Expand Down Expand Up @@ -38,12 +39,16 @@ function useScrollbarWidth() {
}

let backListenerRegistered = false;
let checkedProject = false;

export default function Transitioner() {
const [oldActiveProject, setOldActiveProject] = useState<Project | null>(
null,
);
const [activeProject, setActiveProject] = useAtom(activeProjectAtom);

const routeAfterSlash = usePathname().split("/").slice(1).join("/");

const setIsTransitioning = useSetAtom(isTransitioningAtom);

const scrollbarWidth = useScrollbarWidth();
Expand All @@ -58,6 +63,15 @@ export default function Transitioner() {
});
}

if (!checkedProject) {
checkedProject = true;
for (const project of projects) {
if (routeAfterSlash === project.name) {
setActiveProject(project);
}
}
}

if (oldActiveProject !== activeProject) {
setOldActiveProject(activeProject);
setIsTransitioning(true);
Expand Down
9 changes: 7 additions & 2 deletions app/components/projects/ProjectContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
OPEN_ANIMATION_DURATION,
OPEN_ANIMATION_DURATION_CLASS,
} from "../../utils/constants";
import { activeProjectAtom } from "../../utils/state";
import { activeProjectAtom, isLoadingAtom } from "../../utils/state";

import styles from "./scrollbar.module.css";
import ProjectFeatures from "./ProjectFeatures";
Expand Down Expand Up @@ -38,6 +38,7 @@ export const ProjectContent = memo(function ProjectContent({
const cardRef = useRef<HTMLDivElement>(null);

const setActiveProject = useSetAtom(activeProjectAtom);
const setIsLoading = useSetAtom(isLoadingAtom);

const description = useRef<HTMLDivElement>(null);

Expand Down Expand Up @@ -74,14 +75,18 @@ export const ProjectContent = memo(function ProjectContent({
setTimeout(() => {
setEnableTransition(true);
setIsOpen(true);
setIsLoading(false);
}, 0);
}
}, [isActive, isOpen, enableTransition]);

return (
<OutsideClickHandler
disabled={!isCurrentProject}
onOutsideClick={() => window.history.back()}
onOutsideClick={() => {
window.history.replaceState({ isProject: false }, null, "/");
setActiveProject(null);
}}
>
<div
ref={cardRef}
Expand Down
1 change: 1 addition & 0 deletions app/utils/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ import { Project } from "./projects";

export const activeProjectAtom = atom<Project | null>(null);
export const isTransitioningAtom = atom(false);
export const isLoadingAtom = atom(true);

0 comments on commit 4409ac9

Please sign in to comment.