import { useState, useEffect, useCallback, type RefObject } from 'react'; interface UseCollapsibleHeaderOptions { /** Scroll threshold in pixels before header collapses (default: 50) */ threshold?: number; /** Debounce delay in ms for scroll events (default: 10) */ debounceMs?: number; } interface UseCollapsibleHeaderReturn { /** Whether the header is currently collapsed */ isCollapsed: boolean; /** Manually set collapsed state */ setIsCollapsed: (collapsed: boolean) => void; /** Toggle collapsed state */ toggleCollapsed: () => void; /** Current scroll position */ scrollTop: number; } /** * Hook to manage collapsible header behavior based on scroll position. * * @param scrollContainerRef - Ref to the scrollable container element * @param options - Configuration options * @returns Object with collapsed state and control functions * * @example * ```tsx * const containerRef = useRef(null); * const { isCollapsed } = useCollapsibleHeader(containerRef); * * return ( *
*

Title

*
*
* {content} *
* ); * ``` */ export function useCollapsibleHeader( scrollContainerRef: RefObject, options: UseCollapsibleHeaderOptions = {} ): UseCollapsibleHeaderReturn { const { threshold = 50, debounceMs = 10 } = options; const [isCollapsed, setIsCollapsed] = useState(false); const [scrollTop, setScrollTop] = useState(0); const toggleCollapsed = useCallback(() => { setIsCollapsed(prev => !prev); }, []); useEffect(() => { const container = scrollContainerRef.current; if (!container) return; let timeoutId: ReturnType | null = null; const handleScroll = () => { if (timeoutId) return; // Debounce timeoutId = setTimeout(() => { const currentScrollTop = container.scrollTop; setScrollTop(currentScrollTop); setIsCollapsed(currentScrollTop > threshold); timeoutId = null; }, debounceMs); }; container.addEventListener('scroll', handleScroll, { passive: true }); // Check initial scroll position handleScroll(); return () => { container.removeEventListener('scroll', handleScroll); if (timeoutId) clearTimeout(timeoutId); }; }, [scrollContainerRef, threshold, debounceMs]); return { isCollapsed, setIsCollapsed, toggleCollapsed, scrollTop, }; } export default useCollapsibleHeader;