Spaces:
Running
Running
Download src/components/ScrollToTopButton.jsx from Harry9233/Taste_Rider_Web: direct link, hf CLI and curl.
- Browser
- Download file 2.43 kB
-
https://huggingface.co/spaces/Harry9233/Taste_Rider_Web/resolve/main/src/components/ScrollToTopButton.jsx
- Command line
-
hf download hf://spaces/Harry9233/Taste_Rider_Web/src/components/ScrollToTopButton.jsx
-
curl -L -o ScrollToTopButton.jsx https://huggingface.co/spaces/Harry9233/Taste_Rider_Web/resolve/main/src/components/ScrollToTopButton.jsx
2.43 kB
| import React, { useState, useEffect } from 'react'; | |
| import { motion, AnimatePresence } from 'framer-motion'; | |
| import { ArrowUpCircle } from 'lucide-react'; | |
| import { Button } from '@/components/ui/button'; | |
| const ScrollToTopButton = () => { | |
| const [isVisible, setIsVisible] = useState(false); | |
| const toggleVisibility = () => { | |
| if (window.pageYOffset > 300) { | |
| setIsVisible(true); | |
| } else { | |
| setIsVisible(false); | |
| } | |
| }; | |
| const scrollToTop = () => { | |
| // Get the current scroll position | |
| const startPosition = window.pageYOffset; | |
| // Duration of the scroll animation in milliseconds | |
| const duration = 800; | |
| // Improved easing function for smoother animation | |
| const easeOutCubic = t => 1 - Math.pow(1 - t, 3); | |
| let startTime = null; | |
| const animation = currentTime => { | |
| if (startTime === null) startTime = currentTime; | |
| const timeElapsed = currentTime - startTime; | |
| const progress = Math.min(timeElapsed / duration, 1); | |
| const easedProgress = easeOutCubic(progress); | |
| window.scrollTo(0, startPosition * (1 - easedProgress)); | |
| if (timeElapsed < duration) { | |
| requestAnimationFrame(animation); | |
| } | |
| }; | |
| requestAnimationFrame(animation); | |
| }; | |
| useEffect(() => { | |
| window.addEventListener('scroll', toggleVisibility); | |
| return () => { | |
| window.removeEventListener('scroll', toggleVisibility); | |
| }; | |
| }, []); | |
| return ( | |
| <AnimatePresence> | |
| {isVisible && ( | |
| <motion.div | |
| initial={{ opacity: 0, y: 20 }} | |
| animate={{ opacity: 1, y: 0 }} | |
| exit={{ opacity: 0, y: 20 }} | |
| transition={{ duration: 0.5, ease: "easeInOut" }} | |
| className="fixed bottom-20 left-6 z-50" | |
| > | |
| <motion.div | |
| whileHover={{ scale: 1.1 }} | |
| whileTap={{ scale: 0.9 }} | |
| transition={{ type: "spring", stiffness: 400, damping: 17 }} | |
| > | |
| <Button | |
| onClick={scrollToTop} | |
| variant="outline" | |
| size="icon" | |
| className="bg-amber-600 hover:bg-amber-700 text-white border-amber-700 rounded-full shadow-lg w-12 h-12" | |
| > | |
| <ArrowUpCircle size={28} /> | |
| <span className="sr-only">Scroll to top</span> | |
| </Button> | |
| </motion.div> | |
| </motion.div> | |
| )} | |
| </AnimatePresence> | |
| ); | |
| }; | |
| export default ScrollToTopButton; |