Bluesky app fork with some witchin' additions 馃挮
at main 77 lines 1.6 kB view raw
1import { 2 type LayoutChangeEvent, 3 type StyleProp, 4 View, 5 type ViewStyle, 6} from 'react-native' 7import Animated, { 8 Easing, 9 FadeInUp, 10 FadeOutUp, 11 useAnimatedStyle, 12 useSharedValue, 13 withTiming, 14} from 'react-native-reanimated' 15 16import {IS_IOS, IS_WEB} from '#/env' 17 18type AccordionAnimationProps = React.PropsWithChildren<{ 19 isExpanded: boolean 20 duration?: number 21 style?: StyleProp<ViewStyle> 22}> 23 24function WebAccordion({ 25 isExpanded, 26 duration = 300, 27 style, 28 children, 29}: AccordionAnimationProps) { 30 const heightValue = useSharedValue(0) 31 32 const animatedStyle = useAnimatedStyle(() => { 33 const targetHeight = isExpanded ? heightValue.get() : 0 34 return { 35 height: withTiming(targetHeight, { 36 duration, 37 easing: Easing.out(Easing.cubic), 38 }), 39 overflow: 'hidden', 40 } 41 }) 42 43 const onLayout = (e: LayoutChangeEvent) => { 44 if (heightValue.get() === 0) { 45 heightValue.set(e.nativeEvent.layout.height) 46 } 47 } 48 49 return ( 50 <Animated.View style={[animatedStyle, style]}> 51 <View onLayout={onLayout}>{children}</View> 52 </Animated.View> 53 ) 54} 55 56function MobileAccordion({ 57 isExpanded, 58 duration = 200, 59 style, 60 children, 61}: AccordionAnimationProps) { 62 if (!isExpanded) return null 63 64 return ( 65 <Animated.View 66 style={style} 67 entering={FadeInUp.duration(duration)} 68 exiting={FadeOutUp.duration(duration / 2)} 69 pointerEvents={IS_IOS ? 'auto' : 'box-none'}> 70 {children} 71 </Animated.View> 72 ) 73} 74 75export function AccordionAnimation(props: AccordionAnimationProps) { 76 return IS_WEB ? <WebAccordion {...props} /> : <MobileAccordion {...props} /> 77}