From df762b41548094cd99ab3817728cdd5067898891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yusuf=20Akg=C3=BCl?= <s86116@bht-berlin.de> Date: Mon, 29 May 2023 23:16:17 +0200 Subject: [PATCH] scroll to top btn --- app/(content)/(gaming)/games/page.tsx | 22 +++++++++------- components/filter-sort-games.tsx | 8 ++---- components/icons.tsx | 2 ++ components/infinity-scroll.tsx | 32 ++++++++++++----------- components/scroll-to-top.tsx | 37 +++++++++++++++++++++++++++ 5 files changed, 71 insertions(+), 30 deletions(-) create mode 100644 components/scroll-to-top.tsx diff --git a/app/(content)/(gaming)/games/page.tsx b/app/(content)/(gaming)/games/page.tsx index cacec50..d0f8a42 100644 --- a/app/(content)/(gaming)/games/page.tsx +++ b/app/(content)/(gaming)/games/page.tsx @@ -1,22 +1,26 @@ import Sort from "@/components/filter-sort-games"; import { InfiniteScrollGames } from "@/components/infinity-scroll"; +import ScrollToTop from "@/components/scroll-to-top"; import SearchInput from "@/components/search-input"; // renders a list of games infinitely (presumably) export default async function GamesPage() { return ( - <main className="relative lg:gap-10 xl:grid xl:grid-cols-[1fr_240px]"> - <div className="grid"> - <div className="flex flex-col gap-10 items-center w-full"> - <SearchInput className="p-3 lg:w-2/3 2xl:w-1/3" /> + <> + <main className="relative lg:gap-10 xl:grid xl:grid-cols-[1fr_240px]"> + <div className="grid"> + <div className="flex flex-col gap-10 items-center w-full"> + <SearchInput className="p-3 lg:w-2/3 2xl:w-1/3" /> + </div> + <InfiniteScrollGames /> </div> - <InfiniteScrollGames /> - </div> - <div className="hidden xl:block flex-col md:flex"> - <div className="sticky top-0"> + <div className="hidden xl:block flex-col md:flex"> <Sort /> </div> + </main> + <div className="fixed top-6 left-1/2 -ml-7"> + <ScrollToTop /> </div> - </main> + </> ) } \ No newline at end of file diff --git a/components/filter-sort-games.tsx b/components/filter-sort-games.tsx index a229a73..bf38172 100644 --- a/components/filter-sort-games.tsx +++ b/components/filter-sort-games.tsx @@ -34,13 +34,9 @@ export default function Sort() { .map((param, index) => (index === 0 ? `?${param}` : `&${param}`)) .join(''); - const queryString = `${queryParamString ? `${queryParamString}` : ''}`; + const url = `${pathname}${queryParamString ? `${queryParamString}` : ''}`; - const url = `${pathname}${queryString ? `${queryString}` : ''}`; - - useEffect(() => { - router.push(url); - }, [router, url]); + router.replace(url); function toggleSortOrder() { const newSortOrder = selectedSortOrder === 'desc' ? 'asc' : 'desc'; diff --git a/components/icons.tsx b/components/icons.tsx index ca3cca6..e9a8c6b 100644 --- a/components/icons.tsx +++ b/components/icons.tsx @@ -2,6 +2,7 @@ import { AlertTriangle, ArrowDown, ArrowRight, + ArrowUpToLine, BellRing, Check, ChevronLeft, @@ -72,6 +73,7 @@ export const Icons: IconsType = { moon: Moon, // Dark Mode Toggle Nav arrowdown: ArrowDown, // Descending Sort heart: Heart, // Like Button + arrowupline: ArrowUpToLine, // Back to Top Button close: X, spinner: Loader2, chevronLeft: ChevronLeft, diff --git a/components/infinity-scroll.tsx b/components/infinity-scroll.tsx index d59b27b..179db1d 100644 --- a/components/infinity-scroll.tsx +++ b/components/infinity-scroll.tsx @@ -49,30 +49,32 @@ export function InfiniteScrollGames() { <Card className="p-6"> {status === 'error' ? - (<span>Error: {(error as Error).message}</span>) + (<span>Uh oh... something went wrong: {(error as Error).message}</span>) : (status === 'success' && ( <InfiniteScroll dataLength={data?.pages.length * 20} next={fetchNextPage} hasMore={hasNextPage ? true : false} - loader={<h4>Loading more...</h4>} + loader={ + <h1 className="text-center pt-6"> + <b>Trying to load more...</b> + </h1> + } endMessage={ - <p style={{ textAlign: 'center' }}> - <b>Yay! You have seen it all</b> - </p> + <h1 className="text-center pt-6"> + <b>Yay! You have seen it all!</b> + </h1> } > - <div className=""> - <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 gap-4 lg:gap-8"> - {data.pages.map((page, i) => ( - <Fragment key={i}> - {page.map((game: IGame) => ( - <Game id={game.id} name={game.name} cover={game.cover} key={game.id} /> - ))} - </Fragment> - ))} - </div> + <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 gap-4 lg:gap-8"> + {data.pages.map((page, i) => ( + <Fragment key={i}> + {page.map((game: IGame) => ( + <Game id={game.id} name={game.name} cover={game.cover} key={game.id} /> + ))} + </Fragment> + ))} </div> </InfiniteScroll> ))} diff --git a/components/scroll-to-top.tsx b/components/scroll-to-top.tsx new file mode 100644 index 0000000..bd045be --- /dev/null +++ b/components/scroll-to-top.tsx @@ -0,0 +1,37 @@ +"use client" + +import { cn } from "@/lib/utils"; +import { useEffect, useState } from "react"; +import { Icons } from "./icons"; +import { Button } from "./ui/button"; + +export default function ScrollToTop() { + const [isVisible, setIsVisible] = useState(false); + + const toggleVisibility = () => { + if (window.pageYOffset > 300) { + setIsVisible(true); + } else { + setIsVisible(false); + } + }; + + const scrollToTop = () => { + window.scrollTo({ + top: 0, + behavior: "smooth" + }); + }; + + useEffect(() => { + window.addEventListener("scroll", toggleVisibility); + return () => window.removeEventListener("scroll", toggleVisibility); + }, []); + + return ( + <Button size="lg" onClick={scrollToTop} + className={cn(isVisible ? "block" : "hidden", "")}> + <Icons.arrowupline className="h-3 w-3" aria-hidden="true" /> + </Button> + ); +} \ No newline at end of file -- GitLab