30a42036aa
- Implemented a scroll-to-top button in the viewer UI for better navigation. - Added styles for the scroll-to-top button in viewer.html and viewer-template.html. - Created a new ScrollToTop component to manage visibility and scrolling behavior. - Updated Feed component to include the ScrollToTop component. - Enhanced pagination logic in usePagination hook to prevent stale closures and improve performance. - Modified SDKAgent to include additional observation fields for better data handling.
58 lines
1.3 KiB
TypeScript
58 lines
1.3 KiB
TypeScript
import React, { useState, useEffect } from 'react';
|
|
|
|
interface ScrollToTopProps {
|
|
targetRef: React.RefObject<HTMLDivElement>;
|
|
}
|
|
|
|
export function ScrollToTop({ targetRef }: ScrollToTopProps) {
|
|
const [isVisible, setIsVisible] = useState(false);
|
|
|
|
useEffect(() => {
|
|
const handleScroll = () => {
|
|
const target = targetRef.current;
|
|
if (target) {
|
|
setIsVisible(target.scrollTop > 300);
|
|
}
|
|
};
|
|
|
|
const target = targetRef.current;
|
|
if (target) {
|
|
target.addEventListener('scroll', handleScroll);
|
|
return () => target.removeEventListener('scroll', handleScroll);
|
|
}
|
|
}, []); // Empty deps - only set up listener once on mount
|
|
|
|
const scrollToTop = () => {
|
|
const target = targetRef.current;
|
|
if (target) {
|
|
target.scrollTo({
|
|
top: 0,
|
|
behavior: 'smooth'
|
|
});
|
|
}
|
|
};
|
|
|
|
if (!isVisible) return null;
|
|
|
|
return (
|
|
<button
|
|
onClick={scrollToTop}
|
|
className="scroll-to-top"
|
|
aria-label="Scroll to top"
|
|
>
|
|
<svg
|
|
width="20"
|
|
height="20"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="2"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
>
|
|
<polyline points="18 15 12 9 6 15"></polyline>
|
|
</svg>
|
|
</button>
|
|
);
|
|
}
|