-
Notifications
You must be signed in to change notification settings - Fork 9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feature: added scroll to top button #10174
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import React, { useState, useEffect } from "react" | ||
|
||
const ScrollToTopButton = () => { | ||
const [isVisible, setIsVisible] = useState(false) | ||
const [hideTimeout, setHideTimeout] = useState(null) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. consider using |
||
|
||
const styles = { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Inline styles are not used in this project, so this code doesn't follow the convention. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And for the future. Since the styles object doesn’t depend on any props, it’s best to define it outside the component. This avoids redefining the styles object on each render, improving performance. |
||
button: { | ||
position: "fixed", | ||
bottom: "20px", | ||
right: "20px", | ||
padding: "10px 20px", | ||
fontSize: "18px", | ||
backgroundColor: "rgba(125, 132, 146, 0.8)", | ||
color: "#fff", | ||
border: "2px solid rgba(125, 132, 146, 0.8)", | ||
borderRadius: "5px", | ||
cursor: "pointer", | ||
boxShadow: "0px 4px 6px rgba(0, 0, 0, 0.1), 0 0 15px rgba(125, 132, 146, 0.6)", | ||
transition: "opacity 0.5s ease, box-shadow 0.3s ease", | ||
opacity: isVisible ? 1 : 0, | ||
pointerEvents: isVisible ? "auto" : "none", | ||
}, | ||
icon: { | ||
width: "20px", | ||
height: "20px", | ||
fill: "#fff", | ||
}, | ||
} | ||
|
||
const toggleVisibility = () => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The toggleVisibility function handles both the visibility toggle and timeout reset, which could make the code harder to follow. Consider breaking it up for simplicity: keep the scroll visibility logic and timeout logic separate. Instead of adding this logic directly to that file, consider creating a custom hook. This approach would improve readability and maintain cleaner code. |
||
if (window.scrollY > 300) { | ||
setIsVisible(true) | ||
|
||
if (hideTimeout) { | ||
clearTimeout(hideTimeout) | ||
} | ||
|
||
const timeout = setTimeout(() => { | ||
setIsVisible(false) | ||
}, 3000) | ||
|
||
setHideTimeout(timeout) | ||
} else { | ||
setIsVisible(false) | ||
} | ||
} | ||
|
||
const scrollToTop = () => { | ||
window.scrollTo({ | ||
top: 0, | ||
behavior: "smooth", | ||
}) | ||
} | ||
|
||
useEffect(() => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You’re adding an event listener to window inside |
||
window.addEventListener("scroll", toggleVisibility) | ||
|
||
return () => { | ||
window.removeEventListener("scroll", toggleVisibility) | ||
if (hideTimeout) { | ||
clearTimeout(hideTimeout) | ||
} | ||
} | ||
}, [hideTimeout]) | ||
|
||
return ( | ||
<div> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fragmen will be better here i think. |
||
{isVisible && ( | ||
<button | ||
onClick={scrollToTop} | ||
style={styles.button} | ||
title="Go to top" | ||
aria-label="Go to top" | ||
> | ||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" style={styles.icon} aria-hidden="true"> | ||
<path d="M 17.418 14.908 C 17.69 15.176 18.127 15.176 18.397 14.908 C 18.667 14.64 18.668 14.207 18.397 13.939 L 10.489 6.109 C 10.219 5.841 9.782 5.841 9.51 6.109 L 1.602 13.939 C 1.332 14.207 1.332 14.64 1.602 14.908 C 1.873 15.176 2.311 15.176 2.581 14.908 L 10 7.767 L 17.418 14.908 Z"></path> | ||
</svg> | ||
</button> | ||
)} | ||
</div> | ||
) | ||
} | ||
|
||
export default ScrollToTopButton | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. question - why you prefer default export instead of named export ? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider improving the variable names for better clarity and readability.