From 83ccec5ec42f802a25dc251a6547c45197115f4c Mon Sep 17 00:00:00 2001 From: gbanyan Date: Mon, 17 Nov 2025 21:52:36 +0800 Subject: [PATCH] Add scroll-aware back-to-top button --- components/back-to-top.tsx | 37 +++++++++++++++++++++++++++++++++++++ components/layout-shell.tsx | 2 ++ 2 files changed, 39 insertions(+) create mode 100644 components/back-to-top.tsx diff --git a/components/back-to-top.tsx b/components/back-to-top.tsx new file mode 100644 index 0000000..2ea072f --- /dev/null +++ b/components/back-to-top.tsx @@ -0,0 +1,37 @@ +'use client'; + +import { useEffect, useState } from 'react'; + +export function BackToTop() { + const [visible, setVisible] = useState(false); + + useEffect(() => { + const onScroll = () => { + if (window.scrollY > 400) { + setVisible(true); + } else { + setVisible(false); + } + }; + + onScroll(); + window.addEventListener('scroll', onScroll, { passive: true }); + return () => window.removeEventListener('scroll', onScroll); + }, []); + + if (!visible) return null; + + return ( + + ); +} + diff --git a/components/layout-shell.tsx b/components/layout-shell.tsx index ddc1d4a..b1d03c4 100644 --- a/components/layout-shell.tsx +++ b/components/layout-shell.tsx @@ -1,6 +1,7 @@ import { SiteHeader } from './site-header'; import { SiteFooter } from './site-footer'; import { RightSidebar } from './right-sidebar'; +import { BackToTop } from './back-to-top'; export function LayoutShell({ children }: { children: React.ReactNode }) { return ( @@ -13,6 +14,7 @@ export function LayoutShell({ children }: { children: React.ReactNode }) { + ); }