animation
This commit is contained in:
@@ -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 (
|
||||
<View style={[styles.container, style]}>
|
||||
{isOpen ? (
|
||||
@@ -112,44 +161,63 @@ const ProjectDropDown = ({
|
||||
style={styles.triggerWrapper}
|
||||
onLayout={(event) => setTriggerLayout(event.nativeEvent.layout)}
|
||||
>
|
||||
<BlurView
|
||||
intensity={BUTTON_BLUR_INTENSITY}
|
||||
tint="dark"
|
||||
<Animated.View
|
||||
pointerEvents={isOpen ? "none" : "auto"}
|
||||
style={[
|
||||
styles.dropdownBlur,
|
||||
isDisabled && styles.dropdownBlurDisabled,
|
||||
isOpen && styles.dropdownBlurHidden,
|
||||
styles.dropdownTriggerContainer,
|
||||
{
|
||||
opacity: triggerOpacity,
|
||||
transform: [{ translateY: triggerTranslateY }],
|
||||
},
|
||||
]}
|
||||
>
|
||||
<ProjectRow
|
||||
isTitle={true}
|
||||
isOpen={isOpen}
|
||||
project={currentProject}
|
||||
formatDate={formatDate}
|
||||
onSelect={toggleDropdown}
|
||||
/>
|
||||
</BlurView>
|
||||
<BlurView
|
||||
intensity={BUTTON_BLUR_INTENSITY}
|
||||
tint="dark"
|
||||
style={[
|
||||
styles.dropdownBlur,
|
||||
isDisabled && styles.dropdownBlurDisabled,
|
||||
]}
|
||||
>
|
||||
<ProjectRow
|
||||
isTitle={true}
|
||||
isOpen={isOpen}
|
||||
project={currentProject}
|
||||
formatDate={formatDate}
|
||||
onSelect={toggleDropdown}
|
||||
/>
|
||||
</BlurView>
|
||||
</Animated.View>
|
||||
|
||||
<BlurView
|
||||
intensity={BUTTON_BLUR_INTENSITY}
|
||||
tint="dark"
|
||||
<Animated.View
|
||||
pointerEvents={isOpen ? "auto" : "none"}
|
||||
style={[
|
||||
styles.dropdownOverlay,
|
||||
styles.dropdownOverlayContainer,
|
||||
{ width: dropdownWidth || "100%" },
|
||||
!isOpen && styles.dropdownOverlayHidden,
|
||||
{
|
||||
opacity: dropdownAnimation,
|
||||
transform: [
|
||||
{ translateY: overlayTranslateY },
|
||||
{ scale: overlayScale },
|
||||
],
|
||||
},
|
||||
]}
|
||||
>
|
||||
<ProjectRow
|
||||
isTitle={true}
|
||||
isOpen={isOpen}
|
||||
project={currentProject}
|
||||
formatDate={formatDate}
|
||||
onSelect={toggleDropdown}
|
||||
/>
|
||||
<BlurView
|
||||
intensity={BUTTON_BLUR_INTENSITY}
|
||||
tint="dark"
|
||||
style={styles.dropdownOverlay}
|
||||
>
|
||||
<ProjectRow
|
||||
isTitle={true}
|
||||
isOpen={isOpen}
|
||||
project={currentProject}
|
||||
formatDate={formatDate}
|
||||
onSelect={toggleDropdown}
|
||||
/>
|
||||
|
||||
<View style={styles.dropdownOverlayContent}>
|
||||
<FlatList
|
||||
<View style={styles.dropdownOverlayContent}>
|
||||
<FlatList
|
||||
data={dropdownProjects}
|
||||
keyExtractor={(project, index) =>
|
||||
project?.id || project?.title || `project-${index}`
|
||||
@@ -168,13 +236,14 @@ const ProjectDropDown = ({
|
||||
contentContainerStyle={styles.dropdownListContent}
|
||||
style={styles.dropdownList}
|
||||
/>
|
||||
<GradientButton
|
||||
containerStyle={styles.createButtonContainer}
|
||||
title="Commencer à créer"
|
||||
onPress={handleCreate}
|
||||
/>
|
||||
</View>
|
||||
</BlurView>
|
||||
<GradientButton
|
||||
containerStyle={styles.createButtonContainer}
|
||||
title="Commencer à créer"
|
||||
onPress={handleCreate}
|
||||
/>
|
||||
</View>
|
||||
</BlurView>
|
||||
</Animated.View>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user