From 35f40848335553d13e33b0b160baf7632b0cfb82 Mon Sep 17 00:00:00 2001 From: corgifist Date: Sun, 27 Jul 2025 23:32:45 +0300 Subject: [PATCH] `Project Library` title now fades when scrolling up --- src/app/page.tsx | 7 ++-- .../scroll-fading-title/ScrollFadingTitle.tsx | 24 +++++++++++++ src/components/scroll-fading-title/index.ts | 3 ++ .../SidebarTriggerAdjustable.tsx | 35 +++++++------------ 4 files changed, 44 insertions(+), 25 deletions(-) create mode 100644 src/components/scroll-fading-title/ScrollFadingTitle.tsx create mode 100644 src/components/scroll-fading-title/index.ts diff --git a/src/app/page.tsx b/src/app/page.tsx index 14c0414..0c7a16b 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -32,6 +32,7 @@ import { Sheet, SheetClose, SheetContent, SheetDescription, SheetHeader, SheetTi import { Separator } from "@/components/ui/separator"; import StaticSidebarTrigger from "@/components/static-sidebar-trigger"; import SidebarTriggerAdjustable from "@/components/sidebar-trigger-adjustable"; +import ScrollFadingTitle from "@/components/scroll-fading-title"; type SortingType = "byCreationDate" | "byEditDate" @@ -491,8 +492,10 @@ export default function Home(): ReactNode {
-

Project Library

- {projects && } + +

Project Library

+ {projects && } +
diff --git a/src/components/scroll-fading-title/ScrollFadingTitle.tsx b/src/components/scroll-fading-title/ScrollFadingTitle.tsx new file mode 100644 index 0000000..e53e272 --- /dev/null +++ b/src/components/scroll-fading-title/ScrollFadingTitle.tsx @@ -0,0 +1,24 @@ +import { ComponentProps, useEffect, useRef, useState } from "react"; + +const easeFade = (x: number) => ( + x === 0 ? 0 : Math.pow(2, 10 * x - 10) +); + +export const ScrollFadingTitle = (props: ComponentProps<"div">) => { + const elementRef = useRef(null); + + useEffect(() => { + const handleScroll = () => { + if (!elementRef.current) return; + const opacity = easeFade(1 - (window.scrollY / ( window.innerHeight / 20))); + elementRef.current.style.opacity = `${opacity}`; + }; + + handleScroll(); + window.addEventListener('scroll', handleScroll); + + return () => window.removeEventListener('scroll', handleScroll); + }, [elementRef]); + + return
+}; \ No newline at end of file diff --git a/src/components/scroll-fading-title/index.ts b/src/components/scroll-fading-title/index.ts new file mode 100644 index 0000000..f6d3f4f --- /dev/null +++ b/src/components/scroll-fading-title/index.ts @@ -0,0 +1,3 @@ +import { ScrollFadingTitle } from "./ScrollFadingTitle"; + +export default ScrollFadingTitle; \ No newline at end of file diff --git a/src/components/sidebar-trigger-adjustable/SidebarTriggerAdjustable.tsx b/src/components/sidebar-trigger-adjustable/SidebarTriggerAdjustable.tsx index 085056c..3d02c0f 100644 --- a/src/components/sidebar-trigger-adjustable/SidebarTriggerAdjustable.tsx +++ b/src/components/sidebar-trigger-adjustable/SidebarTriggerAdjustable.tsx @@ -4,43 +4,32 @@ import { cn } from "@/lib/utils"; import { ComponentProps, useEffect, useState } from "react"; const easeSlide = (x: number) => ( - x + 1 - Math.pow(1 - x, 3) ); export const SidebarTriggerAdjustable = (props: ComponentProps<"div">) => { - const [scrollY, setScrollY] = useState(0); - const [windowHeight, setWindowHeight] = useState(1); const isMobile = useIsMobile(); - let ticking = false; - useEffect(() => { + const triggerElement = document.querySelector('div[data-sidebar-trigger="true"]'); + const handleScroll = () => { - if (!ticking) { - window.requestAnimationFrame(() => { - setScrollY(window.scrollY); - ticking = false; - }); + if (!triggerElement) { + console.log("triggerElement is null"); + return; } + const triggerDiv = triggerElement as HTMLDivElement; + const slideAmount = easeSlide(Math.max(0, Math.min(1, window.scrollY / (window.innerHeight / 20)))); + triggerDiv.style.marginLeft = `calc(var(--spacing) * ${12 * slideAmount})`; + triggerDiv.style.paddingTop = `calc(var(--spacing) * ${(isMobile ? 1 : 3) * slideAmount})`; }; - const handleResize = () => setWindowHeight(window.innerHeight); - - setWindowHeight(window.innerHeight); window.addEventListener('scroll', handleScroll); - window.addEventListener('resize', handleResize); return () => { window.removeEventListener('scroll', handleScroll); - window.removeEventListener('resize', handleResize); }; - }, []); + }, [isMobile]); - let slideAmount = Math.max(0, Math.min(1, scrollY / (windowHeight / 20))); - slideAmount = easeSlide(slideAmount); - - return
; + return
; } \ No newline at end of file