Build technical notes archive
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { AnimatePresence, motion, useReducedMotion } from "motion/react";
|
||||
import { ArrowUp } from "lucide-react";
|
||||
|
||||
export function BackToTopButton() {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const prefersReducedMotion = useReducedMotion();
|
||||
|
||||
useEffect(() => {
|
||||
let frame = 0;
|
||||
|
||||
const updateVisibility = () => {
|
||||
frame = 0;
|
||||
setVisible(window.scrollY > 520);
|
||||
};
|
||||
|
||||
const handleScroll = () => {
|
||||
if (frame) {
|
||||
return;
|
||||
}
|
||||
|
||||
frame = window.requestAnimationFrame(updateVisibility);
|
||||
};
|
||||
|
||||
updateVisibility();
|
||||
window.addEventListener("scroll", handleScroll, { passive: true });
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("scroll", handleScroll);
|
||||
if (frame) {
|
||||
window.cancelAnimationFrame(frame);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
const scrollToTop = () => {
|
||||
window.scrollTo({
|
||||
top: 0,
|
||||
behavior: prefersReducedMotion ? "auto" : "smooth",
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<AnimatePresence>
|
||||
{visible ? (
|
||||
<motion.button
|
||||
type="button"
|
||||
aria-label="回到顶部"
|
||||
title="回到顶部"
|
||||
className="fixed bottom-6 right-5 z-50 inline-flex h-12 w-12 items-center justify-center rounded-full border border-cyan-300/35 bg-[#07111f]/95 text-cyan-100 shadow-[0_0_28px_rgba(34,211,238,0.24)] outline-none transition hover:-translate-y-0.5 hover:border-fuchsia-300/70 hover:text-white hover:shadow-[0_0_34px_rgba(217,70,239,0.25)] focus-visible:ring-2 focus-visible:ring-cyan-300 sm:bottom-8 sm:right-8"
|
||||
initial={{ opacity: 0, scale: 0.82, y: 12 }}
|
||||
animate={{ opacity: 1, scale: 1, y: 0 }}
|
||||
exit={{ opacity: 0, scale: 0.82, y: 12 }}
|
||||
transition={{ duration: 0.18, ease: "easeOut" }}
|
||||
onClick={scrollToTop}
|
||||
>
|
||||
<ArrowUp className="h-5 w-5" />
|
||||
</motion.button>
|
||||
) : null}
|
||||
</AnimatePresence>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user