diff --git a/src/components/app/app.tsx b/src/components/app/app.tsx index 0ba5b6d..dd9f0bc 100644 --- a/src/components/app/app.tsx +++ b/src/components/app/app.tsx @@ -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() { + + ); diff --git a/src/components/scroll-to-top/index.ts b/src/components/scroll-to-top/index.ts new file mode 100644 index 0000000..7ac434b --- /dev/null +++ b/src/components/scroll-to-top/index.ts @@ -0,0 +1 @@ +export { ScrollToTop } from './scroll-to-top'; diff --git a/src/components/scroll-to-top/scroll-to-top.module.css b/src/components/scroll-to-top/scroll-to-top.module.css new file mode 100644 index 0000000..c5ab172 --- /dev/null +++ b/src/components/scroll-to-top/scroll-to-top.module.css @@ -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); +} diff --git a/src/components/scroll-to-top/scroll-to-top.tsx b/src/components/scroll-to-top/scroll-to-top.tsx new file mode 100644 index 0000000..8e7462b --- /dev/null +++ b/src/components/scroll-to-top/scroll-to-top.tsx @@ -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 ( + + {isVisible && ( + + + + )} + + ); +}