expo-popcore-app/hooks/use-sticky-tabs.ts

91 lines
2.2 KiB
TypeScript

import { useCallback, useRef, useState } from 'react'
export interface UseStickyTabsReturn {
isSticky: boolean
tabsHeight: number
tabsPositionRef: React.MutableRefObject<number>
titleBarHeightRef: React.MutableRefObject<number>
handleScroll: (scrollY: number) => void
handleTabsLayout: (y: number, height: number) => void
handleTitleBarLayout: (height: number) => void
}
/**
* Hook for managing sticky tabs state and scroll monitoring
*
* This hook extracts the sticky tabs logic from the home page,
* providing a reusable way to handle tab stickiness based on scroll position.
*
* @returns {UseStickyTabsReturn} Object containing sticky state and handlers
*
* @example
* ```tsx
* const {
* isSticky,
* tabsHeight,
* handleScroll,
* handleTabsLayout,
* handleTitleBarLayout
* } = useStickyTabs()
*
* // In ScrollView
* <ScrollView
* onScroll={(e) => handleScroll(e.nativeEvent.contentOffset.y)}
* >
* <View onLayout={(e) => handleTitleBarLayout(e.nativeEvent.layout.height)}>
* <TitleBar />
* </View>
* <View onLayout={(e) => handleTabsLayout(
* e.nativeEvent.layout.y,
* e.nativeEvent.layout.height
* )}>
* <Tabs />
* </View>
* </ScrollView>
*
* // Sticky tabs overlay
* {isSticky && (
* <View style={{ position: 'absolute', top: 0, height: tabsHeight }}>
* <Tabs />
* </View>
* )}
* ```
*/
export function useStickyTabs(): UseStickyTabsReturn {
const [isSticky, setIsSticky] = useState(false)
const [tabsHeight, setTabsHeight] = useState(0)
const tabsPositionRef = useRef(0)
const titleBarHeightRef = useRef(0)
const handleScroll = useCallback((scrollY: number) => {
if (scrollY > tabsPositionRef.current) {
if (!isSticky) {
setIsSticky(true)
}
} else {
if (isSticky) {
setIsSticky(false)
}
}
}, [isSticky])
const handleTabsLayout = useCallback((y: number, height: number) => {
tabsPositionRef.current = y
setTabsHeight(height)
}, [])
const handleTitleBarLayout = useCallback((height: number) => {
titleBarHeightRef.current = height
}, [])
return {
isSticky,
tabsHeight,
tabsPositionRef,
titleBarHeightRef,
handleScroll,
handleTabsLayout,
handleTitleBarLayout,
}
}