All checks were successful
Build Frontend / build (push) Successful in 1m15s
Added 'overscroll-behavior: contain' to body and Chromebook scroll containers to prevent unwanted scroll chaining. Updated scrollToBottom utilities to handle null/undefined containers and errors gracefully. Fixed ChatDetail to use the correct scroll handler function.
106 lines
3.1 KiB
TypeScript
106 lines
3.1 KiB
TypeScript
import { useEffect, useRef } from 'react';
|
|
|
|
/**
|
|
* Hook to enhance scrolling behavior for Chromebooks and touch devices
|
|
*/
|
|
export function useChromebookScroll() {
|
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
|
|
useEffect(() => {
|
|
const container = containerRef.current;
|
|
if (!container) return;
|
|
|
|
// Enhanced scrolling for Chromebooks
|
|
container.style.overscrollBehavior = 'contain';
|
|
|
|
const handleTouchStart = (e: TouchEvent) => {
|
|
// Prevent default touch behavior that might interfere with scrolling
|
|
if (e.touches.length === 1) {
|
|
// Single touch - allow normal scrolling
|
|
return;
|
|
}
|
|
|
|
// Multi-touch - prevent zoom gestures
|
|
if (e.touches.length > 1) {
|
|
e.preventDefault();
|
|
}
|
|
};
|
|
|
|
const handleTouchMove = (e: TouchEvent) => {
|
|
// Allow momentum scrolling on Chromebooks
|
|
if (e.touches.length === 1) {
|
|
// Single touch scrolling - allow default behavior
|
|
return;
|
|
}
|
|
|
|
// Multi-touch - prevent zoom
|
|
if (e.touches.length > 1) {
|
|
e.preventDefault();
|
|
}
|
|
};
|
|
|
|
const handleWheel = (e: WheelEvent) => {
|
|
// Enhanced wheel scrolling for Chromebook trackpads
|
|
const delta = e.deltaY;
|
|
const container = e.currentTarget as HTMLElement;
|
|
|
|
// Smooth scrolling for Chromebook trackpads
|
|
if (Math.abs(delta) > 0) {
|
|
container.scrollBy({
|
|
top: delta * 0.5, // Reduce scroll speed for better control
|
|
behavior: 'smooth'
|
|
});
|
|
}
|
|
};
|
|
|
|
// Add event listeners
|
|
container.addEventListener('touchstart', handleTouchStart, { passive: false });
|
|
container.addEventListener('touchmove', handleTouchMove, { passive: false });
|
|
container.addEventListener('wheel', handleWheel, { passive: true });
|
|
|
|
// Cleanup
|
|
return () => {
|
|
container.removeEventListener('touchstart', handleTouchStart);
|
|
container.removeEventListener('touchmove', handleTouchMove);
|
|
container.removeEventListener('wheel', handleWheel);
|
|
};
|
|
}, []);
|
|
|
|
return containerRef;
|
|
}
|
|
|
|
/**
|
|
* Hook for smooth scrolling to bottom (useful for chat interfaces)
|
|
*/
|
|
export function useSmoothScrollToBottom() {
|
|
const scrollToBottom = (container: HTMLElement | null | undefined) => {
|
|
if (!container || typeof container !== 'object') return;
|
|
|
|
try {
|
|
if ('scrollTo' in container && typeof container.scrollTo === 'function') {
|
|
container.scrollTo({
|
|
top: container.scrollHeight,
|
|
behavior: 'smooth'
|
|
});
|
|
} else {
|
|
container.scrollTop = container.scrollHeight;
|
|
}
|
|
} catch (err) {
|
|
console.error('Error in scrollToBottom:', err);
|
|
// Fallback to direct property assignment if scrollTo fails
|
|
try {
|
|
container.scrollTop = container.scrollHeight;
|
|
} catch (e) { }
|
|
}
|
|
};
|
|
|
|
const scrollToBottomInstant = (container: HTMLElement | null | undefined) => {
|
|
if (!container || typeof container !== 'object') return;
|
|
try {
|
|
container.scrollTop = container.scrollHeight;
|
|
} catch (e) { }
|
|
};
|
|
|
|
return { scrollToBottom, scrollToBottomInstant };
|
|
}
|