Skip to content

Commit 2fc13ba

Browse files
committed
Make about page with fancy animations
1 parent a0319fd commit 2fc13ba

File tree

12 files changed

+345
-17
lines changed

12 files changed

+345
-17
lines changed

package-lock.json

+55
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"@types/react": "18.0.28",
1313
"@types/react-dom": "18.0.11",
1414
"class-variance-authority": "^0.4.0",
15+
"framer-motion": "^9.1.7",
1516
"next": "13.2.4",
1617
"react": "18.2.0",
1718
"react-dom": "18.2.0",

src/assets/images/people/rik.webp

54.9 KB
Binary file not shown.

src/assets/state/team.tsx

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { StaticImageData } from "next/image";
2+
import RikPicture from "@/assets/images/people/rik.webp";
3+
4+
export interface IMember {
5+
name: string;
6+
title: string;
7+
text: string;
8+
image: StaticImageData;
9+
links: {
10+
name: string;
11+
href: string;
12+
}[];
13+
}
14+
15+
const members: IMember[] = [
16+
{
17+
image: RikPicture,
18+
name: "Rik",
19+
title: "Lead Developer & Founder",
20+
text: "As the creator of the project, I am passionate about delivering a top-quality Git client that meets the needs of developers everywhere.",
21+
links: [
22+
{
23+
href: "https://github.com/Rikthepixel",
24+
name: "GitHub"
25+
},
26+
{
27+
href: "mailto:rikdenbreejen@commitrocket.com",
28+
name: "Email"
29+
},
30+
{
31+
href: "https://www.rikdenbreejen.nl",
32+
name: "Website"
33+
},
34+
{
35+
href: "https://www.linkedin.com/in/rik-den-breejen-a84aa71a7/",
36+
name: "LinkedIn"
37+
}
38+
]
39+
}
40+
];
41+
42+
export default members;

src/components/controls/Button.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { twMerge } from "tailwind-merge";
44

55
import { RequiredKeys } from "@/types/utility";
66

7-
export const style = cva("transition-color shadow-sm px-3 py-2 rounded-md", {
7+
export const style = cva("flex items-center justify-center transition-colors shadow-sm px-3 py-2 rounded-md", {
88
variants: {
99
color: {
1010
secondary: "bg-secondary hover:bg-secondary-dark text-secondary-contrast"

src/components/controls/LinkButton.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, { useMemo } from "react";
22
import Link, { LinkProps as InternalLinkProps } from "next/link";
3-
import { cva, VariantProps as GetVariantProps } from "class-variance-authority";
3+
import { VariantProps as GetVariantProps } from "class-variance-authority";
44
import { twMerge } from "tailwind-merge";
55

66
import { RequiredKeys } from "@/types/utility";

src/components/navigation/Header.tsx

+28-4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,37 @@
1-
import React from "react";
1+
import { useRouter } from "next/router";
2+
import React, { ReactNode } from "react";
3+
import { twMerge } from "tailwind-merge";
4+
import Link from "./Link";
25

3-
interface HeaderProps {
6+
export interface HeaderProps {
47

58
}
69

10+
const NavLink = ({ href, currentHref, children }: {
11+
href: string,
12+
currentHref: string,
13+
children: ReactNode;
14+
}) => (
15+
<Link color="primary" className={"text-lg font-bold" + (currentHref === href ? " text-primary-dark" : "")} href={href}>
16+
{children}
17+
</Link>
18+
);
19+
720
const Header = ({ }: HeaderProps) => {
21+
const router = useRouter();
22+
823
return (
9-
<>
10-
</>
24+
<header className="flex items-center w-full gap-12 px-8 py-4">
25+
<Link color="primary" className={"text-4xl font-bold"} href="/">
26+
Commit Rocket
27+
</Link>
28+
<NavLink href="/" currentHref={router.asPath}>
29+
Home
30+
</NavLink>
31+
<NavLink href="/about" currentHref={router.asPath}>
32+
About
33+
</NavLink>
34+
</header>
1135
);
1236
};
1337

src/components/navigation/Link.tsx

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import React, { useMemo } from "react";
2+
import InternalLink, { LinkProps as InternalLinkProps } from "next/link";
3+
import { cva, VariantProps as GetVariantProps } from "class-variance-authority";
4+
import { twMerge } from "tailwind-merge";
5+
6+
import { RequiredKeys } from "@/types/utility";
7+
8+
export const style = cva("transition-colors", {
9+
variants: {
10+
underline: {
11+
true: "underline",
12+
false: ""
13+
},
14+
color: {
15+
primary: "text-primary hover:text-primary-light",
16+
secondary: "text-secondary hover:text-secondary-light"
17+
}
18+
},
19+
defaultVariants: {
20+
underline: false
21+
}
22+
});
23+
24+
export type VariantProps = GetVariantProps<typeof style>;
25+
26+
type LinkProps = {
27+
underline?: boolean;
28+
} & RequiredKeys<VariantProps, "color">
29+
& Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, keyof InternalLinkProps>
30+
& InternalLinkProps
31+
& React.RefAttributes<HTMLAnchorElement>;
32+
33+
const Link = ({ className, color, underline, ...props }: LinkProps) => {
34+
35+
const computedClassName = useMemo(
36+
() => twMerge(style({ color, underline }), className),
37+
[className, color, underline]
38+
);
39+
40+
return (
41+
<InternalLink className={computedClassName} {...props} />
42+
);
43+
};
44+
45+
export default Link;

src/pages/_app.tsx

+58-7
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,74 @@
1-
import Head from "next/head";
2-
import type { AppProps } from 'next/app';
1+
import { useEffect, useRef, useState } from "react";
2+
import { motion, useReducedMotion, MotionConfig, AnimatePresence } from "framer-motion";
33
import { Open_Sans } from 'next/font/google';
4+
import type { AppProps } from 'next/app';
5+
import Head from "next/head";
46

57
import '@/styles/main.css';
8+
import Header from "@/components/navigation/Header";
69

710
const openSans = Open_Sans({
811
subsets: ['latin'],
912
variable: "--font-open-sans"
1013
});
1114

12-
export default function App({ Component, pageProps }: AppProps) {
15+
const pageTransition = {
16+
duration: .35,
17+
ease: "easeOut"
18+
};
19+
20+
const pageAnimation = {
21+
initial: {
22+
opacity: 0,
23+
translateX: "0%"
24+
},
25+
animate: {
26+
opacity: 100,
27+
translateX: "0%",
28+
},
29+
exit: {
30+
opacity: 0,
31+
translateX: "5%"
32+
}
33+
};
34+
35+
export default function App({ Component, pageProps, router }: AppProps) {
36+
const previousPathname = useRef(router.pathname);
37+
const [initialLoad, setIntialLoad] = useState(true);
38+
const reduceMotion = useReducedMotion();
39+
40+
useEffect(() => {
41+
if (previousPathname.current !== router.pathname) setIntialLoad(false);
42+
previousPathname.current = router.pathname;
43+
}, [router.pathname]);
44+
1345
return (
14-
<>
46+
<MotionConfig reducedMotion="user">
1547
<Head>
1648
<title>Commit Rocket</title>
1749
</Head>
18-
<div className="flex flex-col items-center">
19-
<Component className={openSans.variable} {...pageProps} />
50+
<div className={"flex flex-col items-center overflow-auto" + openSans.variable}>
51+
<Header />
52+
53+
<AnimatePresence mode="wait">
54+
<motion.main
55+
key={router.pathname}
56+
className="flex flex-col flex-1 w-full"
57+
initial="initial"
58+
animate="animate"
59+
exit="exit"
60+
transition={pageTransition}
61+
variants={reduceMotion ? {} : pageAnimation}
62+
>
63+
<Component
64+
className=""
65+
initialLoad={initialLoad}
66+
reduceMotion={reduceMotion}
67+
{...pageProps}
68+
/>
69+
</motion.main>
70+
</AnimatePresence>
2071
</div>
21-
</>
72+
</MotionConfig>
2273
);
2374
}

0 commit comments

Comments
 (0)