From 22c67e4db3c45cca7553e41adde63580203e43f5 Mon Sep 17 00:00:00 2001 From: Biki Kalita <86558912+Biki-dev@users.noreply.github.com> Date: Tue, 9 Dec 2025 17:00:33 +0530 Subject: [PATCH 1/3] feat: add global scroll-to-top button feature --- apps/web/src/app/layout.tsx | 4 +- apps/web/src/components/ui/ScrollToTop.tsx | 62 ++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 apps/web/src/components/ui/ScrollToTop.tsx diff --git a/apps/web/src/app/layout.tsx b/apps/web/src/app/layout.tsx index bde677a7..ceb7626a 100644 --- a/apps/web/src/app/layout.tsx +++ b/apps/web/src/app/layout.tsx @@ -10,7 +10,7 @@ import { authConfig } from "@/lib/auth/config"; import { SessionWrapper } from "./SessionWrapper"; import { TRPCProvider } from "@/providers/trpc-provider"; import { GeistSans } from "geist/font/sans"; - +import ScrollToTop from "@/components/ui/ScrollToTop"; // DM Mono - Used for code, terminal, and monospace text const dmMono = localFont({ src: [ @@ -100,6 +100,7 @@ export const metadata: Metadata = { }, }; + export default async function RootLayout({ children, }: Readonly<{ @@ -126,6 +127,7 @@ export default async function RootLayout({ + ); diff --git a/apps/web/src/components/ui/ScrollToTop.tsx b/apps/web/src/components/ui/ScrollToTop.tsx new file mode 100644 index 00000000..b36072b3 --- /dev/null +++ b/apps/web/src/components/ui/ScrollToTop.tsx @@ -0,0 +1,62 @@ + +"use client"; + +import { useState, useEffect } from "react"; +import { ChevronUp } from "lucide-react"; +import { cn } from "@/lib/utils"; + +export default function ScrollToTop() { + const [isVisible, setIsVisible] = useState(false); + + useEffect(() => { + const toggleVisibility = () => { + if (window.scrollY > 300) { + setIsVisible(true); + } else { + setIsVisible(false); + } + }; + + window.addEventListener("scroll", toggleVisibility); + toggleVisibility(); + return () => { + window.removeEventListener("scroll", toggleVisibility); + }; + }, []); + + + const scrollToTop = () => { + window.scrollTo({ + top: 0, + behavior: "smooth", + }); + }; + + return ( + <> + {/* Button only renders when isVisible is true */} + {isVisible && ( + + )} + + ); +} \ No newline at end of file From ca01aafe43315c94024cc7fbc9ac89e3b8153c29 Mon Sep 17 00:00:00 2001 From: Biki Kalita <86558912+Biki-dev@users.noreply.github.com> Date: Tue, 9 Dec 2025 17:15:24 +0530 Subject: [PATCH 2/3] refactor: replace hardcoded hex colors with semantic design tokens --- apps/web/src/components/ui/ScrollToTop.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/web/src/components/ui/ScrollToTop.tsx b/apps/web/src/components/ui/ScrollToTop.tsx index b36072b3..22335a66 100644 --- a/apps/web/src/components/ui/ScrollToTop.tsx +++ b/apps/web/src/components/ui/ScrollToTop.tsx @@ -41,14 +41,14 @@ export default function ScrollToTop() { className={cn( "fixed bottom-8 right-8 z-50", "w-12 h-12 rounded-xl", - "bg-[#1e1e1e] border-2 border-[#252525]", - "hover:border-brand-purple hover:bg-[#252525]", "shadow-lg hover:shadow-xl hover:shadow-brand-purple/20", "transition-all duration-300 ease-in-out", "animate-in fade-in slide-in-from-bottom-4", "cursor-pointer", "active:scale-95", - "focus:outline-none focus:ring-2 focus:ring-brand-purple focus:ring-offset-2 focus:ring-offset-[#101010]" + "bg-surface-elevated border-2 border-border-subtle", + "hover:border-brand-purple hover:bg-surface-elevated-hover", + "focus:outline-none focus:ring-2 focus:ring-brand-purple focus:ring-offset-2 focus:ring-offset-surface-root" )} aria-label="Scroll to top" > From 917517c15836c6751b1a0d93793f76cc1d72b04d Mon Sep 17 00:00:00 2001 From: Biki Kalita <86558912+Biki-dev@users.noreply.github.com> Date: Tue, 9 Dec 2025 17:24:32 +0530 Subject: [PATCH 3/3] fix: correct button border radius and enable group hover effect --- apps/web/src/components/ui/ScrollToTop.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/web/src/components/ui/ScrollToTop.tsx b/apps/web/src/components/ui/ScrollToTop.tsx index 22335a66..af97f95c 100644 --- a/apps/web/src/components/ui/ScrollToTop.tsx +++ b/apps/web/src/components/ui/ScrollToTop.tsx @@ -40,7 +40,8 @@ export default function ScrollToTop() { onClick={scrollToTop} className={cn( "fixed bottom-8 right-8 z-50", - "w-12 h-12 rounded-xl", + "group", + "w-12 h-12 rounded-[16px]", "shadow-lg hover:shadow-xl hover:shadow-brand-purple/20", "transition-all duration-300 ease-in-out", "animate-in fade-in slide-in-from-bottom-4",