Skip to content

Commit 9046da2

Browse files
authored
Merge pull request #145 from Kanishka16garg/feat/back-to-top-reintroduce
fix: reintroduce Back to Top button
2 parents e068963 + e6465d7 commit 9046da2

2 files changed

Lines changed: 47 additions & 11 deletions

File tree

src/app/components/navigation/BackToTopButton.jsx

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,36 +6,70 @@ export default function BackToTopButton() {
66
const [isVisible, setIsVisible] = useState(false);
77

88
useEffect(() => {
9+
const getScrollTop = () =>
10+
window.pageYOffset ||
11+
(document.scrollingElement && document.scrollingElement.scrollTop) ||
12+
document.documentElement.scrollTop ||
13+
document.body.scrollTop ||
14+
0;
15+
916
const onScroll = () => {
10-
setIsVisible(window.scrollY > 300);
17+
setIsVisible(getScrollTop() > 300);
1118
};
19+
20+
// initial check
1221
onScroll();
22+
23+
const mainEl = document.querySelector("main, [data-scroll-container], .app-scroll");
24+
const scrollEl = document.scrollingElement || document.documentElement || document.body;
25+
26+
// attach listeners broadly to catch different scroll container patterns
1327
window.addEventListener("scroll", onScroll, { passive: true });
14-
return () => window.removeEventListener("scroll", onScroll);
28+
try { scrollEl.addEventListener("scroll", onScroll, { passive: true }); } catch {}
29+
if (mainEl && mainEl !== scrollEl) mainEl.addEventListener("scroll", onScroll, { passive: true });
30+
31+
return () => {
32+
window.removeEventListener("scroll", onScroll);
33+
try { scrollEl.removeEventListener("scroll", onScroll); } catch {}
34+
if (mainEl && mainEl !== scrollEl) mainEl.removeEventListener("scroll", onScroll);
35+
};
1536
}, []);
1637

1738
const handleClick = () => {
18-
window.scrollTo({ top: 0, behavior: "smooth" });
39+
const target =
40+
document.scrollingElement ||
41+
document.querySelector("main, [data-scroll-container], .app-scroll") ||
42+
document.documentElement ||
43+
document.body;
44+
try {
45+
target.scrollTo({ top: 0, behavior: "smooth" });
46+
} catch {
47+
window.scrollTo({ top: 0, behavior: "smooth" });
48+
}
1949
};
2050

21-
if (!isVisible) return null;
22-
2351
return (
2452
<button
25-
onClick={handleClick}
53+
data-testid="back-to-top"
2654
aria-label="Back to top"
27-
className="fixed bottom-6 right-6 z-50 rounded-full bg-blue-600 text-white shadow-lg hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 p-3 md:p-4 transition-transform duration-200 hover:scale-105"
55+
title="Back to top"
56+
onClick={handleClick}
57+
className={
58+
"fixed bottom-6 right-6 z-50 rounded-full bg-blue-600 text-white shadow-lg focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 p-3 md:p-4 transition-all duration-200 transform " +
59+
(isVisible
60+
? "opacity-100 scale-100 pointer-events-auto translate-y-0"
61+
: "opacity-0 scale-75 pointer-events-none -translate-y-2")
62+
}
2863
>
2964
<svg
3065
xmlns="http://www.w3.org/2000/svg"
3166
viewBox="0 0 24 24"
3267
fill="currentColor"
3368
className="h-5 w-5 md:h-6 md:w-6"
69+
aria-hidden="true"
3470
>
35-
<path d="M12 20c-.414 0-.75-.336-.75-.75V6.56l-3.72 3.72a.75.75 0 1 1-1.06-1.06l5-5a.75.75 0 0 1 1.06 0l5 5a.75.75 0 1 1-1.06 1.06l-3.72-3.72v12.69c0 .414-.336.75-.75.75Z"/>
71+
<path d="M12 20c-.414 0-.75-.336-.75-.75V6.56l-3.72 3.72a.75.75 0 1 1-1.06-1.06l5-5a.75.75 0 0 1 1.06 0l5 5a.75.75 0 1 1-1.06 1.06l-3.72-3.72v12.69c0 .414-.336.75-.75.75Z" />
3672
</svg>
3773
</button>
3874
);
39-
}
40-
41-
75+
}

src/app/layout.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { ThemeProvider } from "./context/ThemeContext";
44
import { AnalyticsProvider } from "./context/AnalyticsContext";
55
import { I18nProvider } from "./context/I18nContext";
66
import Footer from "./pages/Footer";
7+
import BackToTopButton from "./components/navigation/BackToTopButton";
78

89
export const metadata = {
910
title: "Open Source Component Library",
@@ -37,6 +38,7 @@ export default function RootLayout({ children }) {
3738
</AnalyticsProvider>
3839
</ThemeProvider>
3940
</I18nProvider>
41+
<BackToTopButton />
4042
</body>
4143
</html>
4244
);

0 commit comments

Comments
 (0)