Skip to content

Commit 9cda929

Browse files
authored
webiste: add scroll top btn (#535)
Signed-off-by: yuluo-yx <[email protected]>
1 parent 2f1debf commit 9cda929

File tree

3 files changed

+163
-0
lines changed

3 files changed

+163
-0
lines changed
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import React, { useEffect, useState } from 'react'
2+
import styles from './styles.module.css'
3+
4+
export default function ScrollToTop(): React.ReactElement {
5+
const [isVisible, setIsVisible] = useState(false)
6+
7+
useEffect(() => {
8+
const toggleVisibility = () => {
9+
if (window.pageYOffset > 300) {
10+
setIsVisible(true)
11+
}
12+
else {
13+
setIsVisible(false)
14+
}
15+
}
16+
17+
window.addEventListener('scroll', toggleVisibility)
18+
19+
return () => {
20+
window.removeEventListener('scroll', toggleVisibility)
21+
}
22+
}, [])
23+
24+
const scrollToTop = () => {
25+
window.scrollTo({
26+
top: 0,
27+
behavior: 'smooth',
28+
})
29+
}
30+
31+
return (
32+
<>
33+
{isVisible && (
34+
<button
35+
onClick={scrollToTop}
36+
className={styles.scrollToTop}
37+
aria-label="Scroll to top"
38+
>
39+
<svg
40+
width="24"
41+
height="24"
42+
viewBox="0 0 24 24"
43+
fill="none"
44+
xmlns="http://www.w3.org/2000/svg"
45+
>
46+
<path
47+
d="M12 19V5M12 5L5 12M12 5L19 12"
48+
stroke="currentColor"
49+
strokeWidth="2"
50+
strokeLinecap="round"
51+
strokeLinejoin="round"
52+
/>
53+
</svg>
54+
</button>
55+
)}
56+
</>
57+
)
58+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
.scrollToTop {
2+
position: fixed;
3+
bottom: 2rem;
4+
right: 2rem;
5+
width: 50px;
6+
height: 50px;
7+
border-radius: 50%;
8+
background: linear-gradient(45deg, var(--tech-primary-blue), var(--tech-accent-purple));
9+
color: white;
10+
border: none;
11+
cursor: pointer;
12+
display: flex;
13+
align-items: center;
14+
justify-content: center;
15+
box-shadow: 0 4px 12px rgba(9, 105, 218, 0.3);
16+
transition: all 0.3s ease;
17+
z-index: 999;
18+
opacity: 0;
19+
transform: translateY(20px);
20+
animation: fadeInUp 0.3s ease forwards;
21+
}
22+
23+
@keyframes fadeInUp {
24+
to {
25+
opacity: 1;
26+
transform: translateY(0);
27+
}
28+
}
29+
30+
.scrollToTop:hover {
31+
transform: translateY(-4px) scale(1.1);
32+
box-shadow: 0 8px 20px rgba(9, 105, 218, 0.4);
33+
}
34+
35+
.scrollToTop:active {
36+
transform: translateY(-2px) scale(1.05);
37+
}
38+
39+
[data-theme='dark'] .scrollToTop {
40+
background: linear-gradient(45deg, var(--tech-primary-blue), var(--tech-accent-orange));
41+
box-shadow: 0 4px 12px rgba(88, 166, 255, 0.4);
42+
}
43+
44+
[data-theme='dark'] .scrollToTop:hover {
45+
box-shadow: 0 8px 20px rgba(88, 166, 255, 0.5);
46+
}
47+
48+
@media (max-width: 768px) {
49+
.scrollToTop {
50+
bottom: 1.5rem;
51+
right: 1.5rem;
52+
width: 45px;
53+
height: 45px;
54+
}
55+
}
56+
57+
.scrollToTop::before {
58+
content: '';
59+
position: absolute;
60+
top: 0;
61+
left: 0;
62+
right: 0;
63+
bottom: 0;
64+
border-radius: 50%;
65+
background: inherit;
66+
opacity: 0;
67+
animation: pulse 2s ease-out infinite;
68+
}
69+
70+
@keyframes pulse {
71+
0% {
72+
transform: scale(1);
73+
opacity: 0.5;
74+
}
75+
50% {
76+
transform: scale(1.1);
77+
opacity: 0.3;
78+
}
79+
100% {
80+
transform: scale(1.3);
81+
opacity: 0;
82+
}
83+
}
84+
85+
.scrollToTop svg {
86+
position: relative;
87+
z-index: 1;
88+
transition: transform 0.3s ease;
89+
}
90+
91+
.scrollToTop:hover svg {
92+
transform: translateY(-2px);
93+
}

website/src/theme/Root.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import React from 'react'
2+
import Root from '@theme-original/Root'
3+
import ScrollToTop from '../components/ScrollToTop'
4+
5+
export default function RootWrapper(props: any): React.ReactElement {
6+
return (
7+
<>
8+
<Root {...props} />
9+
<ScrollToTop />
10+
</>
11+
)
12+
}

0 commit comments

Comments
 (0)