UNPKG

react-native-modern-elements

Version:

A modern, customizable UI component library for React Native

48 lines (47 loc) 1.94 kB
import { Extrapolate, interpolate, useAnimatedScrollHandler, useAnimatedStyle, useSharedValue, withTiming, } from "react-native-reanimated"; const useScrollShadowAnimation = ({ threshold = 5, // very small scroll needed to show shadow backgroundColor = "#fff", borderWidth = 0.7, borderBottomWidthColors = "rgba(0,0,0,0.2)", } = {}) => { const scrollY = useSharedValue(0); const scrollHandler = useAnimatedScrollHandler({ onScroll: (event) => { scrollY.value = event.contentOffset.y; }, }); const animatedShadowStyle = useAnimatedStyle(() => { const opacity = interpolate(scrollY.value, [0, threshold], [0, 0.3], // appear immediately stronger Extrapolate.CLAMP); const radius = interpolate(scrollY.value, [0, threshold], [0, 6], // bigger shadow radius quickly Extrapolate.CLAMP); const elevation = interpolate(scrollY.value, [0, threshold], [0, 8], // stronger elevation Extrapolate.CLAMP); // ✅ zIndex based on scroll return { shadowColor: "black", shadowOpacity: opacity, shadowRadius: radius, elevation, backgroundColor, zIndex: 10, }; }); // borderBttom const borderAnimatedStyle = useAnimatedStyle(() => { return { borderBottomWidth: borderWidth, // always same width borderBottomColor: scrollY.value > 0 ? withTiming(borderBottomWidthColors, { duration: 120 }) // when scrolling : withTiming("transparent", { duration: 120 }), // when not scrolling }; }); const staticShadowOffset = { shadowOffset: { width: 0, height: 3 }, // bottom shadow only }; return { scrollHandler, animatedShadowStyle, staticShadowOffset, scrollY, borderAnimatedStyle, }; }; export default useScrollShadowAnimation;