import React, { useEffect, useState } from 'react';
import styled from 'styled-components';
import v from '../../styles/Variables';
interface Props {
/**
* The icon or words that will show on the button, must be wrapped in valid JSX like a span
*/
delimiter?: string;
/**
* Classes to be applied to the delimiter itself (wrapped in a span)
*/
delimiterTheme?: string;
/**
* When done scrolling, where focus should go for screen readers
*/
focusEl?: string;
/**
* Position from the right
*/
right: number;
/**
* The height and width of the button
*/
size?: number;
/**
* An ID of where to scroll to, if excluded, will be the top of the page
*/
target?: string | null;
/**
* Classes applied to the button wrapper
*/
theme?: string;
/**
* How far the user has to scroll before the button shows, if excluded, it will always show
*/
threshold?: number;
}
interface Style {
size?: number;
right?: number;
}
const ScrollToTop = ({ delimiter = '↑', delimiterTheme, focusEl = '#app', right = 40, size = 40, target, theme, threshold = 100 }: Props) => {
const [show, showSetter] = useState(threshold ? false : true);
useEffect(() => {
if (window)
window.addEventListener('scroll', () => {
if (threshold && window.scrollY > threshold) {
showSetter(true);
} else {
showSetter(false);
}
});
}, [threshold]);
const scrollToTop = () => {
if (!target) {
window.scrollTo({ top: 0, behavior: 'smooth' });
} else {
const elmnt = document.getElementById(target);
if (elmnt) elmnt.scrollIntoView({ behavior: 'smooth' });
}
};
return (
{show === true && (
{
scrollToTop();
const el = document.querySelector(focusEl) as HTMLElement;
if (el !== null) el.focus();
}}
size={size}
right={right}
aria-label="Scroll back to top"
>
{delimiter}
)}
);
};
export default ScrollToTop;
/* styles */
const STT = styled.button