Skip to content

Commit 3fec0c9

Browse files
committed
feat: extend scroll to top/bottom buttons to showcase in all the pages in this website
1 parent c5e3673 commit 3fec0c9

2 files changed

Lines changed: 44 additions & 15 deletions

File tree

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
import React, { useState, useEffect } from "react";
2-
import { FaArrowUp } from "react-icons/fa";
2+
import { FaArrowDown, FaArrowUp } from "react-icons/fa";
33

44
export default function ScrollBottomToTop() {
5-
const [isVisible, setIsVisible] = useState(false);
6-
7-
const toggleVisibility = () => {
8-
if (window.pageYOffset > 300) {
9-
setIsVisible(true);
10-
} else {
11-
setIsVisible(false);
12-
}
5+
const [showTopButton, setShowTopButton] = useState(false);
6+
const [showBottomButton, setShowBottomButton] = useState(false);
7+
8+
const updateVisibility = () => {
9+
const scrollTop = window.pageYOffset;
10+
const documentHeight = document.documentElement.scrollHeight;
11+
const viewportHeight = window.innerHeight;
12+
13+
setShowTopButton(scrollTop > 300);
14+
setShowBottomButton(scrollTop + viewportHeight < documentHeight - 300);
1315
};
1416

1517
const scrollToTop = () => {
@@ -19,26 +21,50 @@ export default function ScrollBottomToTop() {
1921
});
2022
};
2123

24+
const scrollToBottom = () => {
25+
window.scrollTo({
26+
top: document.documentElement.scrollHeight,
27+
behavior: "smooth",
28+
});
29+
};
30+
2231
useEffect(() => {
23-
window.addEventListener("scroll", toggleVisibility);
32+
updateVisibility();
33+
window.addEventListener("scroll", updateVisibility);
34+
window.addEventListener("resize", updateVisibility);
2435

2536
return () => {
26-
window.removeEventListener("scroll", toggleVisibility);
37+
window.removeEventListener("scroll", updateVisibility);
38+
window.removeEventListener("resize", updateVisibility);
2739
};
2840
}, []);
2941

42+
if (!showTopButton && !showBottomButton) {
43+
return null;
44+
}
45+
3046
return (
31-
<div className="scroll-to-top">
32-
{isVisible && (
47+
<div className="scroll-to-top fixed right-5 bottom-5 z-50 flex flex-col gap-3">
48+
{showTopButton && (
3349
<button
34-
aria-label="Scroll to top"
50+
aria-label="Scroll to top"
3551
onClick={scrollToTop}
36-
className="fixed right-5 bottom-5 z-50 cursor-pointer rounded-full border-none bg-gray-700 p-3 text-white shadow-lg transition-opacity duration-300 hover:bg-gray-800 dark:bg-gray-600 dark:hover:bg-gray-700"
52+
className="cursor-pointer rounded-full border-none bg-gray-700 p-3 text-white shadow-lg transition-opacity duration-300 hover:bg-gray-800 dark:bg-gray-600 dark:hover:bg-gray-700"
3753
style={{ backgroundColor: "var(--ifm-color-primary)" }}
3854
>
3955
<FaArrowUp />
4056
</button>
4157
)}
58+
{showBottomButton && (
59+
<button
60+
aria-label="Scroll to bottom"
61+
onClick={scrollToBottom}
62+
className="cursor-pointer rounded-full border-none bg-gray-700 p-3 text-white shadow-lg transition-opacity duration-300 hover:bg-gray-800 dark:bg-gray-600 dark:hover:bg-gray-700"
63+
style={{ backgroundColor: "var(--ifm-color-primary)" }}
64+
>
65+
<FaArrowDown />
66+
</button>
67+
)}
4268
</div>
4369
);
4470
}

src/theme/Root.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import clsx from "clsx"; // Import clsx for conditional classes
66
import styles from "./Root.module.css"; // Import the CSS module
77
import { useLocation } from "@docusaurus/router";
88
import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
9+
import ScrollBottomToTop from "@site/src/components/scroll/bottom-to-top";
910

1011
// A simple Trophy SVG icon component
1112
function TrophyIcon() {
@@ -233,6 +234,8 @@ export default function Root({ children }: { children: React.ReactNode }) {
233234
</div>
234235
)}
235236

237+
<ScrollBottomToTop />
238+
236239
{process.env.NODE_ENV === "production" && <Analytics />}
237240
</>
238241
);

0 commit comments

Comments
 (0)