feat: add scroll to top component

This commit is contained in:
MAZE 2023-10-31 15:01:33 +03:30
parent 3b33e09547
commit 3c1c27b2fd
4 changed files with 70 additions and 0 deletions

View File

@ -8,6 +8,7 @@ import { Container } from '@/components/container';
import { StoreConsumer } from '@/components/store-consumer';
import { Buttons } from '@/components/buttons';
import { Categories } from '@/components/categories';
import { ScrollToTop } from '@/components/scroll-to-top';
import { SnackbarProvider } from '@/contexts/snackbar';
import { sounds } from '@/data/sounds';
@ -55,6 +56,8 @@ export function App() {
<Buttons />
<Categories categories={allCategories} />
</Container>
<ScrollToTop />
</StoreConsumer>
</SnackbarProvider>
);

View File

@ -0,0 +1 @@
export { ScrollToTop } from './scroll-to-top';

View File

@ -0,0 +1,17 @@
.button {
position: fixed;
z-index: 99;
bottom: 20px;
left: 20px;
display: flex;
width: 45px;
height: 45px;
align-items: center;
justify-content: center;
border: 1px solid var(--color-neutral-300);
border-radius: 50%;
background-color: var(--color-neutral-100);
color: var(--color-foreground);
cursor: pointer;
font-size: var(--font-md);
}

View File

@ -0,0 +1,49 @@
import { useState, useEffect } from 'react';
import { BiUpArrowAlt } from 'react-icons/bi';
import { motion, AnimatePresence } from 'framer-motion';
import { mix, fade, slideY } from '@/lib/motion';
import styles from './scroll-to-top.module.css';
export function ScrollToTop() {
const TOP = 50;
const [isVisible, setIsVisible] = useState(false);
const scrollToTop = () => {
window.scrollTo({ behavior: 'smooth', top: 0 });
};
useEffect(() => {
const onScroll = () => {
setIsVisible(document.documentElement.scrollTop >= TOP);
};
onScroll();
document.addEventListener('scroll', onScroll);
return () => document.removeEventListener('scroll', onScroll);
}, []);
const variants = mix(fade(), slideY(10, 0));
return (
<AnimatePresence>
{isVisible && (
<motion.button
animate="show"
aria-label="Scroll to top"
className={styles.button}
exit="hidden"
initial="hidden"
variants={variants}
onClick={scrollToTop}
>
<BiUpArrowAlt />
</motion.button>
)}
</AnimatePresence>
);
}