diff --git a/src/components/ProjectDropDown/ProjectDropDown.js b/src/components/ProjectDropDown/ProjectDropDown.js index 0ce6825..a43fdce 100644 --- a/src/components/ProjectDropDown/ProjectDropDown.js +++ b/src/components/ProjectDropDown/ProjectDropDown.js @@ -1,5 +1,7 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { + Animated, + Easing, FlatList, Image, Pressable, @@ -43,6 +45,7 @@ const ProjectDropDown = ({ }) => { const [isOpen, setIsOpen] = useState(false); const [triggerLayout, setTriggerLayout] = useState(null); + const dropdownAnimation = useRef(new Animated.Value(0)).current; const normalizedProjects = Array.isArray(projects) ? projects : []; const isDisabled = normalizedProjects.length === 0; @@ -102,6 +105,52 @@ const ProjectDropDown = ({ [triggerLayout], ); + useEffect(() => { + Animated.timing(dropdownAnimation, { + toValue: isOpen ? 1 : 0, + duration: 220, + easing: isOpen ? Easing.out(Easing.cubic) : Easing.in(Easing.cubic), + useNativeDriver: true, + }).start(); + }, [dropdownAnimation, isOpen]); + + const overlayTranslateY = useMemo( + () => + dropdownAnimation.interpolate({ + inputRange: [0, 1], + outputRange: [-12, 0], + }), + [dropdownAnimation], + ); + + const overlayScale = useMemo( + () => + dropdownAnimation.interpolate({ + inputRange: [0, 1], + outputRange: [0.96, 1], + }), + [dropdownAnimation], + ); + + const triggerOpacity = useMemo( + () => + dropdownAnimation.interpolate({ + inputRange: [0, 1], + outputRange: [1, 0], + extrapolate: "clamp", + }), + [dropdownAnimation], + ); + + const triggerTranslateY = useMemo( + () => + dropdownAnimation.interpolate({ + inputRange: [0, 1], + outputRange: [0, -6], + }), + [dropdownAnimation], + ); + return ( {isOpen ? ( @@ -112,44 +161,63 @@ const ProjectDropDown = ({ style={styles.triggerWrapper} onLayout={(event) => setTriggerLayout(event.nativeEvent.layout)} > - - - + + + + - - + + - - + project?.id || project?.title || `project-${index}` @@ -168,13 +236,14 @@ const ProjectDropDown = ({ contentContainerStyle={styles.dropdownListContent} style={styles.dropdownList} /> - - - + + + + ); @@ -295,29 +364,30 @@ const styles = StyleSheet.create({ dropdownBlurDisabled: { opacity: 0.6, }, - dropdownBlurHidden: { - opacity: 0, - pointerEvents: "none", - }, triggerWrapper: { position: "relative", zIndex: 3, }, - dropdownOverlay: { + dropdownTriggerContainer: { + width: "100%", + }, + dropdownOverlayContainer: { position: "absolute", top: 0, left: 0, borderRadius: 16, + overflow: "hidden", + zIndex: 4, + elevation: 4, + maxHeight: 400, + }, + dropdownOverlay: { + flex: 1, + width: "100%", paddingHorizontal: 8, paddingVertical: 8, gap: 9, maxHeight: 400, - zIndex: 4, - elevation: 4, - overflow: "hidden", - }, - dropdownOverlayHidden: { - opacity: 0, }, dropdownOverlayContent: { maxHeight: 260,