From 4293eef8248ebb8453a50337ea0d1d763df9206a Mon Sep 17 00:00:00 2001 From: Gregor Lohaus Date: Fri, 13 Mar 2026 22:18:44 +0100 Subject: [PATCH] working animations --- src/app/_components/Animated/AnimateIn.tsx | 5 ++-- .../Animated/AnimatedBackGroundContainer.tsx | 6 +++-- .../Animated/AnimatedPageTitle.tsx | 13 ++++------- src/app/_components/ThemeIcon.tsx | 18 +++++++++++---- src/app/_components/ThemeSwitch.tsx | 3 +++ src/app/_providers/GsapProvicer.tsx | 4 ++-- src/app/_providers/ThemeProvider.tsx | 23 ++++--------------- src/app/music/page.tsx | 17 +++++++------- 8 files changed, 44 insertions(+), 45 deletions(-) diff --git a/src/app/_components/Animated/AnimateIn.tsx b/src/app/_components/Animated/AnimateIn.tsx index c743630..5130df9 100644 --- a/src/app/_components/Animated/AnimateIn.tsx +++ b/src/app/_components/Animated/AnimateIn.tsx @@ -1,5 +1,6 @@ import { useGSAP } from "@gsap/react"; -import { useLayoutEffect, +import { useEffect, +useLayoutEffect, useRef, type ReactNode } from "react"; import { useGsapContext } from "~/app/_providers/GsapProvicer"; import { SplitText } from "gsap/SplitText"; @@ -7,7 +8,7 @@ import gsap from 'gsap' const AnimateTextIn = ({children,animation="type",position}:{children:ReactNode,animation?:"type"|"slide",position:gsap.Position}) => { const el = useRef(null) const gsapContext = useGsapContext(); - useGSAP(() => { + useEffect(() => { console.log("aniamte text with:",position) const tl = gsap.timeline(); const chars = new SplitText(el.current,{type:'chars'}) diff --git a/src/app/_components/Animated/AnimatedBackGroundContainer.tsx b/src/app/_components/Animated/AnimatedBackGroundContainer.tsx index 9f358f9..76eb714 100644 --- a/src/app/_components/Animated/AnimatedBackGroundContainer.tsx +++ b/src/app/_components/Animated/AnimatedBackGroundContainer.tsx @@ -102,7 +102,10 @@ export default function AnimatedBackgroundContainer({ const [mounted, setMounted] = useState(false); const { resolvedTheme } = useTheme(); - const isDark = resolvedTheme === "dark"; + let isDark = resolvedTheme === "dark"; + if (resolvedTheme == undefined) { + isDark = true; + } const palette = isDark ? PALETTES.dark : PALETTES.light; /* Spawn particles */ @@ -264,7 +267,6 @@ export default function AnimatedBackgroundContainer({ minHeight: "100vh", width: "100%", overflow: "hidden", - backgroundColor: palette.base, transition: "background-color 0.6s ease", }} > diff --git a/src/app/_components/Animated/AnimatedPageTitle.tsx b/src/app/_components/Animated/AnimatedPageTitle.tsx index a2e191a..f99016b 100644 --- a/src/app/_components/Animated/AnimatedPageTitle.tsx +++ b/src/app/_components/Animated/AnimatedPageTitle.tsx @@ -7,19 +7,16 @@ const AnimatedPageTitle = ( ) => { const el = useRef(null) const gsapContext = useGsapContext(); - useGSAP(() => { + useEffect(() => { console.log("add animated title with:",position) - const tl = gsap.timeline(); - tl.addLabel("title") const split = new SplitText(el.current, { type: "chars" }) - tl.from(el.current, { opacity: 0 }) - tl.from(split.chars, { + gsapContext?.addAnimation(gsap.to(el.current, { opacity: 100 }),position) + gsapContext?.addAnimation(gsap.from(split.chars, { stagger: 0.05, rotate: -90, opacity: 0, x: -10 - }, '>') - gsapContext?.addAnimation(tl,position) + }),'>') }) return ( -

{text}

+

{text}

) } diff --git a/src/app/_components/ThemeIcon.tsx b/src/app/_components/ThemeIcon.tsx index 4162143..4b66d5c 100644 --- a/src/app/_components/ThemeIcon.tsx +++ b/src/app/_components/ThemeIcon.tsx @@ -4,10 +4,18 @@ import { Moon, Sun } from "lucide-react" import { useEffect } from "react" type Props = {activeTheme:string|undefined} const ThemeIcon = (props:Props) => { - if (props.activeTheme == "dark") { - return () - } else { - return () - } + return ( + <> + {props.activeTheme && props.activeTheme == 'dark' && + + } + {props.activeTheme && props.activeTheme == 'light' && + + } + {!props.activeTheme && + + } + + ) } export default ThemeIcon; diff --git a/src/app/_components/ThemeSwitch.tsx b/src/app/_components/ThemeSwitch.tsx index c490947..df26e9a 100644 --- a/src/app/_components/ThemeSwitch.tsx +++ b/src/app/_components/ThemeSwitch.tsx @@ -8,6 +8,9 @@ import ThemeIcon from "./ThemeIcon" export function ThemeSwitch() { const { setTheme, theme } = useTheme() + if (!theme) { + setTheme('dark') + } const toggleTheme = () => { setTheme(theme == "dark" ? "light" : "dark") } diff --git a/src/app/_providers/GsapProvicer.tsx b/src/app/_providers/GsapProvicer.tsx index f9acb01..c20101f 100644 --- a/src/app/_providers/GsapProvicer.tsx +++ b/src/app/_providers/GsapProvicer.tsx @@ -27,12 +27,11 @@ export default function GsapProvider({ children }: { children: ReactNode }) { if (!tl.current) { tl.current = gsap.timeline({ paused: true }) } - console.log("resuming timeline:",tl.current) return () => { console.log("gsap cleanup") } }) const addAnimation = useCallback((animation: gsap.core.TimelineChild, position: gsap.Position) => { - console.log("add animation to:", position) + console.log("add animation to:", position, tl.current !== undefined) tl.current?.add(animation, position); },[]) const resetTimeline = useCallback(() => { @@ -41,6 +40,7 @@ export default function GsapProvider({ children }: { children: ReactNode }) { tl.current = gsap.timeline({paused:true}) },[]) const resumeTimeline = useCallback(() => { + console.log("resuming timeline:",tl.current) tl.current?.resume() },[]) return ( diff --git a/src/app/_providers/ThemeProvider.tsx b/src/app/_providers/ThemeProvider.tsx index f17ca88..901925c 100644 --- a/src/app/_providers/ThemeProvider.tsx +++ b/src/app/_providers/ThemeProvider.tsx @@ -1,23 +1,10 @@ 'use client' -import * as React from "react" import { ThemeProvider as NextThemesProvider } from "next-themes" export default function ThemeProvider({children}:{children: React.ReactNode}) { - const [mounted,setMounted] = React.useState(false) - React.useEffect(() => { - setMounted(true) - }) - if (mounted) { - return ( - - {children} - - ) - } else { - return ( - <> - {children} - - ) - } + return ( + + {children} + + ) } diff --git a/src/app/music/page.tsx b/src/app/music/page.tsx index cbf5a71..37e1a51 100644 --- a/src/app/music/page.tsx +++ b/src/app/music/page.tsx @@ -1,6 +1,8 @@ 'use client' import { useGSAP } from "@gsap/react"; -import { useLayoutEffect, +import { useEffect, +useEffectEvent, +useLayoutEffect, useRef } from "react"; import { trpc } from "~/app/_trpc/Client"; import * as Card from "~/components/ui/card"; @@ -8,21 +10,20 @@ import { useGsapContext } from "../_providers/GsapProvicer"; import AnimatedPageTitle from "../_components/Animated/AnimatedPageTitle"; import { Spinner } from "~/components/ui/spinner"; import AnimateTextIn from "../_components/Animated/AnimateIn"; -import gsap from 'gsap' export default function MusicPage() { const { data: tracks, isLoading } = trpc.music.list.useQuery(); - const container = useRef(null) const gsapContext = useGsapContext(); - useGSAP(() => { - gsapContext?.resumeTimeline() + useEffect(() => { + if (tracks) { + gsapContext?.resumeTimeline() + } return () => { console.log("page cleanup") gsapContext?.resetTimeline() } - }); - + },[tracks]); return (<> -
+