import classNames from 'classnames'; import throttle from 'lodash/throttle'; import React, { useState, useEffect, useCallback } from 'react'; import { useIntl, MessageDescriptor } from 'react-intl'; import Icon from 'soapbox/components/icon'; import { Text } from 'soapbox/components/ui'; import { useSettings } from 'soapbox/hooks'; interface IScrollTopButton { /** Callback when clicked, and also when scrolled to the top. */ onClick: () => void, /** Number of unread items. */ count: number, /** Message to display in the button (should contain a `{count}` value). */ message: MessageDescriptor, /** Distance from the top of the screen (scrolling down) before the button appears. */ threshold?: number, /** Distance from the top of the screen (scrolling up) before the action is triggered. */ autoloadThreshold?: number, } /** Floating new post counter above timelines, clicked to scroll to top. */ const ScrollTopButton: React.FC = ({ onClick, count, message, threshold = 400, autoloadThreshold = 50, }) => { const intl = useIntl(); const settings = useSettings(); const [scrolled, setScrolled] = useState(false); const autoload = settings.get('autoloadTimelines') === true; const handleScroll = useCallback(throttle(() => { const { scrollTop } = (document.scrollingElement || document.documentElement); if (autoload && scrollTop <= autoloadThreshold) { onClick(); } if (scrollTop > threshold) { setScrolled(true); } else { setScrolled(false); } }, 150, { trailing: true }), [autoload, threshold, autoloadThreshold]); const scrollUp = () => { window.scrollTo({ top: 0 }); }; const handleClick: React.MouseEventHandler = () => { setTimeout(scrollUp, 10); onClick(); }; useEffect(() => { window.addEventListener('scroll', handleScroll); return () => { window.removeEventListener('scroll', handleScroll); }; }, []); const visible = count > 0 && scrolled; const classes = classNames('left-1/2 -translate-x-1/2 fixed top-20 z-50', { 'hidden': !visible, }); return (
{(count > 0) && ( {intl.formatMessage(message, { count })} )}
); }; export default ScrollTopButton;