add animations, scroll

This commit is contained in:
Tom Elliott 2025-05-30 11:10:10 +12:00
parent df4c38061e
commit daa46bdf3d
7 changed files with 108 additions and 9 deletions

View File

@ -16,6 +16,7 @@
"@tailwindcss/postcss": "^4.1.4", "@tailwindcss/postcss": "^4.1.4",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"graphql": "^16.10.0", "graphql": "^16.10.0",
"lenis": "^1.3.4",
"motion": "^12.15.0", "motion": "^12.15.0",
"next": "15.3.1", "next": "15.3.1",
"payload": "^3.35.1", "payload": "^3.35.1",

21
pnpm-lock.yaml generated
View File

@ -26,6 +26,9 @@ importers:
graphql: graphql:
specifier: ^16.10.0 specifier: ^16.10.0
version: 16.10.0 version: 16.10.0
lenis:
specifier: ^1.3.4
version: 1.3.4(react@19.1.0)
motion: motion:
specifier: ^12.15.0 specifier: ^12.15.0
version: 12.15.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) version: 12.15.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
@ -2422,6 +2425,20 @@ packages:
resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==} resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==}
engines: {node: '>=0.10'} engines: {node: '>=0.10'}
lenis@1.3.4:
resolution: {integrity: sha512-WIGk8wiV2ABm/T7M+NC+tAV8fjzNJD1J4z11aZ3mTtx7WAZX/4QdCNhBO0g/TqXISA+/3hTbzrPC4FW1nhoNMQ==}
peerDependencies:
'@nuxt/kit': '>=3.0.0'
react: '>=17.0.0'
vue: '>=3.0.0'
peerDependenciesMeta:
'@nuxt/kit':
optional: true
react:
optional: true
vue:
optional: true
levn@0.4.1: levn@0.4.1:
resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
engines: {node: '>= 0.8.0'} engines: {node: '>= 0.8.0'}
@ -5933,6 +5950,10 @@ snapshots:
dependencies: dependencies:
language-subtag-registry: 0.3.23 language-subtag-registry: 0.3.23
lenis@1.3.4(react@19.1.0):
optionalDependencies:
react: 19.1.0
levn@0.4.1: levn@0.4.1:
dependencies: dependencies:
prelude-ls: 1.2.1 prelude-ls: 1.2.1

View File

@ -0,0 +1,51 @@
"use client";
import { RichText } from "@payloadcms/richtext-lexical/react";
import { motion, useScroll, useTransform } from "motion/react";
import { useEffect, useRef } from "react";
export default function HeroIntro({
title,
desc,
}: {
title: string;
desc: any;
}) {
const containerRef = useRef(null);
const { scrollYProgress } = useScroll({
target: containerRef,
offset: ["start 0.5", "start start"],
});
const titleY = useTransform(scrollYProgress, [0, 1], [-100, 0]);
const paraOpacity = useTransform(scrollYProgress, [0.5, 1], [0, 1]);
const paraY = useTransform(scrollYProgress, [0.5, 1], [20, 0]);
return (
<div className="h-screen bg-black flex justify-center">
<div
className="w-full h-full border border-white max-w-6xl p-12 grid grid-cols-2 gap-12"
ref={containerRef}
>
<div className="flex-1 flex flex-col justify-center gap-8">
<motion.h2
style={{ opacity: scrollYProgress, y: titleY }}
className="text-5xl tracking-tight leading-tight"
>
{title}
</motion.h2>
<motion.div
style={{
opacity: paraOpacity,
y: paraY,
}}
>
<RichText
data={desc}
className="text-white text-2xl leading-tight"
/>
</motion.div>
</div>
</div>
</div>
);
}

View File

@ -0,0 +1,19 @@
"use client";
import { ReactNode, useEffect } from "react";
import Lenis from "lenis";
export default function ({ children }: { children: ReactNode }) {
useEffect(() => {
const lenis = new Lenis();
// Use requestAnimationFrame to continuously update the scroll
function raf(time: number) {
lenis.raf(time);
requestAnimationFrame(raf);
}
requestAnimationFrame(raf);
}, []);
return <>{children}</>;
}

View File

@ -1,7 +1,9 @@
import { getPayload } from "payload"; import { getPayload } from "payload";
import config from "@payload-config"; import config from "@payload-config";
import ScrollingNumbers from "./components/Hero/ScrollingNumbers"; import ScrollingNumbers from "./components/Home/ScrollingNumbers";
import { letters } from "./components/Hero/letters"; import { letters } from "./components/Home/letters";
import HeroIntro from "./components/Home/Hero/01-intro";
import SmoothScroll from "./components/SmoothScroll";
const randomNumbers = Array.from({ length: 50 }).map((i) => const randomNumbers = Array.from({ length: 50 }).map((i) =>
Array.from({ length: 200 }).map( Array.from({ length: 200 }).map(
@ -11,17 +13,22 @@ const randomNumbers = Array.from({ length: 50 }).map((i) =>
export default async function Home() { export default async function Home() {
const payload = await getPayload({ config }); const payload = await getPayload({ config });
const { titleGroup } = await payload.findGlobal({ const { titleGroup, heroGroup } = await payload.findGlobal({
slug: "homeHero", slug: "homeHero",
}); });
return ( return (
<div className=""> <SmoothScroll>
<div className="text-white">
<div className="h-screen pt-[var(--header-height)] flex flex-col items-center justify-end text-white pb-[10vh] relative"> <div className="h-screen pt-[var(--header-height)] flex flex-col items-center justify-end text-white pb-[10vh] relative">
<ScrollingNumbers numbers={randomNumbers} /> <ScrollingNumbers numbers={randomNumbers} />
<h1 className="text-8xl max-w-6xl z-10">{titleGroup.title}</h1> <h1 className="text-8xl max-w-6xl z-10">{titleGroup.title}</h1>
</div> </div>
<div className="h-screen bg-accent-700">hello</div> <HeroIntro
title={heroGroup.heroTitle}
desc={heroGroup.heroDescription}
/>
</div> </div>
</SmoothScroll>
); );
} }