54 lines
1.3 KiB
TypeScript
54 lines
1.3 KiB
TypeScript
import { cn } from "@/lib/utils";
|
|
import { ReactNode, useEffect, useState } from "react";
|
|
|
|
type Props = {
|
|
threshold?: number;
|
|
behavior?: ScrollBehavior;
|
|
children: ReactNode;
|
|
classes?: {
|
|
onVisibleClasses?: string;
|
|
onHiddenClasses?: string;
|
|
generalClasses?: string;
|
|
};
|
|
};
|
|
|
|
export default function GoToTopBase(props: Props) {
|
|
const { threshold = 300, behavior = "smooth", children, classes } = props;
|
|
|
|
const [visible, setVisible] = useState<boolean>(false);
|
|
|
|
useEffect(() => {
|
|
const handleScroll = () => {
|
|
setVisible(window.scrollY > threshold);
|
|
};
|
|
|
|
window.addEventListener("scroll", handleScroll);
|
|
|
|
return () => {
|
|
window.removeEventListener("scroll", handleScroll);
|
|
};
|
|
}, [threshold]);
|
|
|
|
const scrollToTop = () => {
|
|
window.scrollTo({
|
|
top: 0,
|
|
behavior,
|
|
});
|
|
};
|
|
|
|
return (
|
|
<button
|
|
type="button"
|
|
onClick={scrollToTop}
|
|
className={cn(
|
|
classes?.generalClasses,
|
|
"z-10 p-0 fixed bottom-4 md:bottom-32 right-2 md:right-16 transition-all duration-300",
|
|
visible
|
|
? `opacity-100 translate-y-0 ${classes?.onVisibleClasses}`
|
|
: `opacity-0 translate-y-4 pointer-events-none ${classes?.onHiddenClasses}`,
|
|
)}
|
|
>
|
|
{children}
|
|
</button>
|
|
);
|
|
}
|