Files
web_hghl_h5/src/components/home/floating-actions.tsx
T
谢宇宁andClaude Opus 5.5 61d0a11dfa Initial commit
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 17:51:31 +07:00

60 lines
2.0 KiB
TypeScript

"use client";
import { useSyncExternalStore } from "react";
import { openAppDownload, useAppDownloadHref } from "@/components/download/download-dialog";
function subscribe(callback: () => void) {
window.addEventListener("scroll", callback, { passive: true });
window.addEventListener("resize", callback);
return () => {
window.removeEventListener("scroll", callback);
window.removeEventListener("resize", callback);
};
}
const getPastFirstScreen = () => window.scrollY > window.innerHeight;
const getServerSnapshot = () => false;
export function FloatingActions() {
const showToTop = useSyncExternalStore(subscribe, getPastFirstScreen, getServerSnapshot);
const downloadHref = useAppDownloadHref();
return (
<div data-component="floating-actions" className="fixed right-3 bottom-20 z-40 flex flex-col items-center gap-3 lg:right-6 lg:bottom-24 lg:gap-4">
<button
type="button"
aria-label="回到顶部"
aria-hidden={!showToTop}
tabIndex={showToTop ? 0 : -1}
onClick={() => window.scrollTo({ top: 0, behavior: "smooth" })}
className={`cursor-pointer size-11 transition-[opacity,translate] duration-300 lg:size-[60px] ${
showToTop ? "opacity-100" : "pointer-events-none translate-y-2 opacity-0"
}`}
>
<img src="/images/toTop.png" alt="" className="size-full" />
</button>
{downloadHref ? (
<a
href={downloadHref}
target="_blank"
rel="noopener noreferrer"
aria-label="立即下载"
className="size-[52px] lg:size-[68px]"
>
<img src="/images/download.png" alt="" className="size-full" />
</a>
) : (
<button
type="button"
aria-label="立即下载"
onClick={() => openAppDownload()}
className="size-[52px] cursor-pointer lg:size-[68px]"
>
<img src="/images/download.png" alt="" className="size-full" />
</button>
)}
</div>
);
}