91 lines
2.2 KiB
TypeScript
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,
|
|
}
|
|
}
|