Fix tab scroll arrows not updating at scroll end
- Add debounced scroll-end detection (150ms) for trackpad/touch scrolling - Add scrollend event listener for native browser support - Add 350ms timeout fallback after arrow button clicks - Arrows now update immediately when reaching scroll boundaries Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -40,6 +40,7 @@ const TabsScroller = forwardRef<HTMLDivElement, TabsScrollerProps>(
|
|||||||
const { tabBarPosition } = useTheme();
|
const { tabBarPosition } = useTheme();
|
||||||
const sliderRef = useRef<HTMLDivElement | null>(null);
|
const sliderRef = useRef<HTMLDivElement | null>(null);
|
||||||
const rafRef = useRef(0);
|
const rafRef = useRef(0);
|
||||||
|
const scrollEndTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||||
const [showLeft, setShowLeft] = useState(false);
|
const [showLeft, setShowLeft] = useState(false);
|
||||||
const [showRight, setShowRight] = useState(false);
|
const [showRight, setShowRight] = useState(false);
|
||||||
const heightRef = useRef(0);
|
const heightRef = useRef(0);
|
||||||
@@ -156,8 +157,19 @@ const TabsScroller = forwardRef<HTMLDivElement, TabsScrollerProps>(
|
|||||||
if (!node) return undefined;
|
if (!node) return undefined;
|
||||||
const container = node.closest('.page-tabs-container, .admin-tabs-container');
|
const container = node.closest('.page-tabs-container, .admin-tabs-container');
|
||||||
|
|
||||||
const handleScroll = () => scheduleOverflowUpdate();
|
const handleScroll = () => {
|
||||||
|
scheduleOverflowUpdate();
|
||||||
|
// Debounced scroll-end detection for trackpad/touch scrolling
|
||||||
|
if (scrollEndTimeoutRef.current) {
|
||||||
|
clearTimeout(scrollEndTimeoutRef.current);
|
||||||
|
}
|
||||||
|
scrollEndTimeoutRef.current = setTimeout(() => {
|
||||||
|
updateOverflow();
|
||||||
|
}, 150);
|
||||||
|
};
|
||||||
|
const handleScrollEnd = () => updateOverflow();
|
||||||
node.addEventListener('scroll', handleScroll, { passive: true });
|
node.addEventListener('scroll', handleScroll, { passive: true });
|
||||||
|
node.addEventListener('scrollend', handleScrollEnd, { passive: true });
|
||||||
let resizeObserver: ResizeObserver | null = null;
|
let resizeObserver: ResizeObserver | null = null;
|
||||||
if (typeof ResizeObserver !== 'undefined') {
|
if (typeof ResizeObserver !== 'undefined') {
|
||||||
resizeObserver = new ResizeObserver(() => scheduleOverflowUpdate());
|
resizeObserver = new ResizeObserver(() => scheduleOverflowUpdate());
|
||||||
@@ -176,6 +188,10 @@ const TabsScroller = forwardRef<HTMLDivElement, TabsScrollerProps>(
|
|||||||
}
|
}
|
||||||
return () => {
|
return () => {
|
||||||
node.removeEventListener('scroll', handleScroll);
|
node.removeEventListener('scroll', handleScroll);
|
||||||
|
node.removeEventListener('scrollend', handleScrollEnd);
|
||||||
|
if (scrollEndTimeoutRef.current) {
|
||||||
|
clearTimeout(scrollEndTimeoutRef.current);
|
||||||
|
}
|
||||||
resizeObserver?.disconnect();
|
resizeObserver?.disconnect();
|
||||||
if (typeof window !== 'undefined') {
|
if (typeof window !== 'undefined') {
|
||||||
window.removeEventListener('resize', scheduleOverflowUpdate);
|
window.removeEventListener('resize', scheduleOverflowUpdate);
|
||||||
@@ -222,8 +238,12 @@ const TabsScroller = forwardRef<HTMLDivElement, TabsScrollerProps>(
|
|||||||
left: direction === 'left' ? -step : step,
|
left: direction === 'left' ? -step : step,
|
||||||
behavior: 'smooth'
|
behavior: 'smooth'
|
||||||
});
|
});
|
||||||
|
// Force update after smooth scroll completes (fallback for browsers without scrollend)
|
||||||
|
setTimeout(() => {
|
||||||
|
updateOverflow();
|
||||||
|
}, 350);
|
||||||
},
|
},
|
||||||
[scrollStep]
|
[scrollStep, updateOverflow]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handlePointerDown = useCallback((event: PointerEvent<HTMLDivElement>) => {
|
const handlePointerDown = useCallback((event: PointerEvent<HTMLDivElement>) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user