From 145248b70af471cef19b262ad02b54d55039a9cf Mon Sep 17 00:00:00 2001 From: simisdav55-oss Date: Thu, 28 May 2026 18:01:28 +0800 Subject: [PATCH] feat(ui): add floating Scroll-to-Top button with smooth scroll and fade-in/out transitions (Fixes #250) --- Frontend/src/App.jsx | 3 ++ .../components/shared/ScrollToTopButton.jsx | 43 +++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 Frontend/src/components/shared/ScrollToTopButton.jsx diff --git a/Frontend/src/App.jsx b/Frontend/src/App.jsx index c0b210073..e0f282272 100644 --- a/Frontend/src/App.jsx +++ b/Frontend/src/App.jsx @@ -11,6 +11,7 @@ import { NotFound } from "./components/ui/not-found-2"; import useTicketStore from "./store/ticketStore"; import Toaster from "./components/shared/Toaster"; import BugReportWidget from "./components/shared/BugReportWidget"; +import ScrollToTopButton from "./components/shared/ScrollToTopButton"; import useRealtimeNotifications from "./hooks/useRealtimeNotifications"; // Auth Components @@ -230,6 +231,7 @@ function App() { + @@ -248,6 +250,7 @@ function App() { + diff --git a/Frontend/src/components/shared/ScrollToTopButton.jsx b/Frontend/src/components/shared/ScrollToTopButton.jsx new file mode 100644 index 000000000..4e83c597b --- /dev/null +++ b/Frontend/src/components/shared/ScrollToTopButton.jsx @@ -0,0 +1,43 @@ +import React, { useState, useEffect } from "react"; +import { ChevronUp } from "lucide-react"; + +const ScrollToTopButton = () => { + const [isVisible, setIsVisible] = useState(false); + + useEffect(() => { + const toggleVisibility = () => { + setIsVisible(window.scrollY > 300); + }; + + window.addEventListener("scroll", toggleVisibility, { passive: true }); + return () => window.removeEventListener("scroll", toggleVisibility); + }, []); + + const scrollToTop = () => { + window.scrollTo({ top: 0, behavior: "smooth" }); + }; + + return ( + + ); +}; + +export default ScrollToTopButton;