animation

This commit is contained in:
Thomas Demirdjian
2025-10-03 17:25:44 +02:00
parent 45b7571c14
commit 3d14e47770
+116 -46
View File
@@ -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,