diff --git a/src/app/components/landing/BackToTopButton.tsx b/src/app/components/landing/BackToTopButton.tsx new file mode 100644 index 0000000..d0ce012 --- /dev/null +++ b/src/app/components/landing/BackToTopButton.tsx @@ -0,0 +1,68 @@ +"use client"; + +import { ArrowUp } from "lucide-react"; +import { CSSProperties, useEffect, useState } from "react"; + +export function BackToTopButton() { + const [isVisible, setIsVisible] = useState(false); + const [scrollProgress, setScrollProgress] = useState(0); + + useEffect(() => { + let frameId: number | null = null; + + const updateScrollState = () => { + const scrollTop = window.scrollY; + const scrollableHeight = document.documentElement.scrollHeight - window.innerHeight; + const nextProgress = scrollableHeight > 0 ? Math.min(100, Math.max(0, (scrollTop / scrollableHeight) * 100)) : 0; + + setIsVisible(scrollTop > 120); + setScrollProgress(nextProgress); + frameId = null; + }; + + const requestUpdate = () => { + if (frameId === null) { + frameId = window.requestAnimationFrame(updateScrollState); + } + }; + + requestUpdate(); + window.addEventListener("scroll", requestUpdate, { passive: true }); + window.addEventListener("resize", requestUpdate); + + return () => { + window.removeEventListener("scroll", requestUpdate); + window.removeEventListener("resize", requestUpdate); + if (frameId !== null) { + window.cancelAnimationFrame(frameId); + } + }; + }, []); + + const handleClick = () => { + const prefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches; + + window.scrollTo({ + top: 0, + behavior: prefersReducedMotion ? "auto" : "smooth", + }); + }; + + return ( + + + + + + + ); +} diff --git a/src/app/components/landing/SiteFooter.tsx b/src/app/components/landing/SiteFooter.tsx new file mode 100644 index 0000000..92c34b8 --- /dev/null +++ b/src/app/components/landing/SiteFooter.tsx @@ -0,0 +1,49 @@ +import Link from "next/link"; +import { Globe2, Mail, MapPin } from "lucide-react"; +import { navigation } from "@/app/content"; + +export function SiteFooter() { + return ( + + ); +}