Skip to content

Commit

Permalink
add scroll to top button
Browse files Browse the repository at this point in the history
  • Loading branch information
marsidev committed May 18, 2022
1 parent c25da74 commit dd31ffe
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 21 deletions.
90 changes: 90 additions & 0 deletions components/ScrollToTop.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import React, {useEffect, useState} from "react";
import {IconButton, IconButtonProps} from "@chakra-ui/react";
import {motion, Variants} from "framer-motion";
import {FaChevronUp as UpIcon} from "react-icons/fa";

const variants: Variants = {
initial: {
opacity: 0,
scale: 0,
},
animate: {
opacity: 1,
scale: 1,
transition: {duration: 0.1, ease: "easeOut"},
},
tap: {
scale: 0.9,
transition: {duration: 0.1, ease: "easeOut"},
},
hover: {
scale: 1.05,
transition: {duration: 0.1, ease: "easeOut"},
},
};

const MotionIconButton = motion<IconButtonProps>(IconButton);

const ScrollToTop: React.FC = ({...props}) => {
const [showButton, setShowButton] = useState(false);
const bgColor = "blackAlpha.800";
const activeBgColor = "blackAlpha.700";

const scrollToTop = () => {
window.scroll({
top: 0,
behavior: "smooth",
});
};

useEffect(() => {
window.addEventListener("scroll", () => {
// show the button after scrolling down 400px or more
if (window.pageYOffset > 400) {
setShowButton(true);
} else {
setShowButton(false);
}
});

return () => window.removeEventListener("scroll", () => {});
}, []);

if (!showButton) return null;

return (
<MotionIconButton
_active={{bg: activeBgColor}}
_focus={{bg: activeBgColor}}
_hover={{bg: activeBgColor}}
animate="animate"
aria-label="Scroll to top"
bg={bgColor}
border="none"
borderRadius={9999}
bottom={{
base: "20px",
md: "70px",
lg: "70px",
xl: "20px",
}}
boxShadow="rgba(0, 0, 0, 0.19) 0px 4px 12px, rgba(0, 0, 0, 0.23) 0px 4px 4px"
color="white"
fontSize="20px"
icon={<UpIcon />}
initial="initial"
pos="fixed"
right="20px"
size="lg"
variant="solid"
variants={variants}
whileHover="hover"
whileTap="tap"
zIndex={9999}
onClick={scrollToTop}
{...props}
/>
);
};

export default ScrollToTop;
57 changes: 37 additions & 20 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"framer-motion": "^6.3.3",
"next": "12.1.6",
"react": "18.1.0",
"react-dom": "18.1.0"
"react-dom": "18.1.0",
"react-icons": "^4.3.1"
},
"devDependencies": {
"@types/node": "^17.0.34",
Expand Down
2 changes: 2 additions & 0 deletions pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import {ChakraProvider, Container} from "@chakra-ui/react";

import Navbar from "../components/Navbar";
import theme from "../theme";
import ScrollToTop from "../components/ScrollToTop";

function App({Component, pageProps}: AppProps) {
return (
<ChakraProvider theme={theme}>
<Container backgroundColor="white" height="100%" maxWidth="container.xl">
<Navbar />
<Component {...pageProps} />
<ScrollToTop />
</Container>
</ChakraProvider>
);
Expand Down

0 comments on commit dd31ffe

Please sign in to comment.