mirror of
https://github.com/remvze/moodist.git
synced 2025-09-29 15:30:49 -04:00
feat: add scroll to top component
This commit is contained in:
parent
3b33e09547
commit
3c1c27b2fd
@ -8,6 +8,7 @@ import { Container } from '@/components/container';
|
|||||||
import { StoreConsumer } from '@/components/store-consumer';
|
import { StoreConsumer } from '@/components/store-consumer';
|
||||||
import { Buttons } from '@/components/buttons';
|
import { Buttons } from '@/components/buttons';
|
||||||
import { Categories } from '@/components/categories';
|
import { Categories } from '@/components/categories';
|
||||||
|
import { ScrollToTop } from '@/components/scroll-to-top';
|
||||||
import { SnackbarProvider } from '@/contexts/snackbar';
|
import { SnackbarProvider } from '@/contexts/snackbar';
|
||||||
|
|
||||||
import { sounds } from '@/data/sounds';
|
import { sounds } from '@/data/sounds';
|
||||||
@ -55,6 +56,8 @@ export function App() {
|
|||||||
<Buttons />
|
<Buttons />
|
||||||
<Categories categories={allCategories} />
|
<Categories categories={allCategories} />
|
||||||
</Container>
|
</Container>
|
||||||
|
|
||||||
|
<ScrollToTop />
|
||||||
</StoreConsumer>
|
</StoreConsumer>
|
||||||
</SnackbarProvider>
|
</SnackbarProvider>
|
||||||
);
|
);
|
||||||
|
1
src/components/scroll-to-top/index.ts
Normal file
1
src/components/scroll-to-top/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { ScrollToTop } from './scroll-to-top';
|
17
src/components/scroll-to-top/scroll-to-top.module.css
Normal file
17
src/components/scroll-to-top/scroll-to-top.module.css
Normal 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);
|
||||||
|
}
|
49
src/components/scroll-to-top/scroll-to-top.tsx
Normal file
49
src/components/scroll-to-top/scroll-to-top.tsx
Normal 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>
|
||||||
|
);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user