Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[UX Reliability] Improve the bottom modal animations #55157

Merged
Changes from 1 commit
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
fb2f774
feat: change modal animation library
BartoszGrajdek Nov 6, 2024
1d83349
Merge remote-tracking branch 'origin/main' into @BartoszGrajdek/react…
BartoszGrajdek Nov 7, 2024
442b29d
adding some types, and do some refactor
sumo-slonik Nov 7, 2024
0770e20
working on null handling and linter problems
sumo-slonik Nov 7, 2024
51e30ab
Merge branch '@BartoszGrajdek/react-native-modal-refactor' into @Bart…
sumo-slonik Nov 7, 2024
fed11de
fix types and build error
sumo-slonik Nov 8, 2024
e51ff8a
fix linters problems
sumo-slonik Nov 8, 2024
61d4bf3
fix typo in TransactionType
sumo-slonik Nov 8, 2024
e7b1bb5
fix permissions issue
sumo-slonik Nov 8, 2024
2d43ab0
fix issue with to little height of container
sumo-slonik Nov 12, 2024
ed4e2e9
Merge branch 'main' into @BartoszGrajdek/react-native-modal-refactor-…
sumo-slonik Nov 14, 2024
3ad4eab
fix problem with no handling gestures
sumo-slonik Nov 14, 2024
1e78131
Merge pull request #133 from software-mansion-labs/@BartoszGrajdek/re…
sumo-slonik Nov 15, 2024
fc04fa1
refactor: ts & eslint cleanup
BartoszGrajdek Nov 15, 2024
ad079da
add callbacks to animations instead of timeout
sumo-slonik Nov 18, 2024
dd1ff93
fix hideModalContentWhileAnimating
sumo-slonik Nov 18, 2024
96de617
work in progress on any types
sumo-slonik Nov 18, 2024
b2ab25c
fix emoji picker tab
sumo-slonik Nov 18, 2024
5c2b0f6
add swipe animations using react reanimate
sumo-slonik Nov 19, 2024
a95e496
refactor and clean code
sumo-slonik Nov 20, 2024
d9d2df3
Update SearchRouterModal.tsx
sumo-slonik Nov 20, 2024
6ac6696
changes from Bartek CR
sumo-slonik Nov 25, 2024
525f9ca
Merge remote-tracking branch 'origin/main' into @BartoszGrajdek/react…
BartoszGrajdek Dec 12, 2024
50ea848
Merge branch '@BartoszGrajdek/react-native-modal-refactor' into @Bart…
sumo-slonik Dec 18, 2024
61f207a
feat: add handling for different modal types
BartoszGrajdek Dec 18, 2024
dee6299
Merge branch '@BartoszGrajdek/react-native-modal-refactor' into @Bart…
sumo-slonik Dec 18, 2024
0312e11
fix merge problems
sumo-slonik Dec 18, 2024
afcb7db
Modal code refactor
BartoszGrajdek Dec 18, 2024
17fbefe
[49354] Migrate react-native-modal to reanimated
BartoszGrajdek Jan 13, 2025
757aaa6
chore: resolve merge conflicts
BartoszGrajdek Jan 23, 2025
6735c18
refactor: address review comments & remove gesture handling
BartoszGrajdek Jan 23, 2025
ed6f506
Merge remote-tracking branch 'origin/main' into @BartoszGrajdek/react…
BartoszGrajdek Jan 23, 2025
5daefab
fix: enable new modal in PopoverWithMeasuredContent-related components
BartoszGrajdek Jan 27, 2025
27271a8
chore: resolve merge conflicts
BartoszGrajdek Jan 28, 2025
d400ad4
fix: floating action button performance issues
BartoszGrajdek Jan 28, 2025
bd4d1cd
refactor: remove duplicated opacity on modal backdrop
BartoszGrajdek Jan 28, 2025
02d93f8
fix: bottom-docked modal regressions
BartoszGrajdek Jan 29, 2025
10ddb0b
fix: TS error
BartoszGrajdek Jan 29, 2025
0fd231d
Merge remote-tracking branch 'origin/main' into @BartoszGrajdek/react…
BartoszGrajdek Jan 29, 2025
14b1d84
fix: keyframe mock
BartoszGrajdek Jan 29, 2025
495d21b
chore: migrate only FAB
BartoszGrajdek Jan 31, 2025
9f5ae9b
chore: remove unnecessary changes
BartoszGrajdek Jan 31, 2025
6b7ef68
fix: reanimated keyframe easing
BartoszGrajdek Jan 31, 2025
24c77d0
fix: reanimated keyframe easing
BartoszGrajdek Feb 3, 2025
70bf577
chore: resolve merge conflicts
BartoszGrajdek Feb 3, 2025
38a61f3
chore: resolve merge conflicts
BartoszGrajdek Feb 6, 2025
e57e097
Merge remote-tracking branch 'origin/main' into @BartoszGrajdek/react…
BartoszGrajdek Feb 7, 2025
caa8d4e
chore: resolve merge conflicts
BartoszGrajdek Feb 17, 2025
4d87305
refactor: move animation timing to CONST & add display names
BartoszGrajdek Feb 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
refactor and clean code
  • Loading branch information
sumo-slonik committed Nov 20, 2024
commit a95e496916ffe097bb4fa05b86738ca72bd1e277
7 changes: 2 additions & 5 deletions src/components/Modal/ReactNativeModal/Container.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import React from 'react';
import type {SharedValue} from 'react-native-reanimated';
import Animated, {runOnJS, SlideInDown, SlideOutDown, useAnimatedStyle} from 'react-native-reanimated';
import type ModalProps from './types';
import type {ContainerProps} from './types';

function Container({
style,
...props
}: ModalProps & {onOpenCallBack: () => void; onCloseCallBack: () => void; panPosition?: {translateX: SharedValue<number>; translateY: SharedValue<number>}}) {
function Container({style, ...props}: ModalProps & ContainerProps) {
const animatedStyles = useAnimatedStyle(() => {
if (!props.panPosition) {
return {};
18 changes: 3 additions & 15 deletions src/components/Modal/ReactNativeModal/Modal.tsx
Original file line number Diff line number Diff line change
@@ -113,12 +113,11 @@ function ReactNativeModal(incomingProps: ModalProps) {
return false;
};

const handleTransition = (type: TransitionType) => {
const handleTransition = () => {
const shouldAnimate = isVisible !== isContainerOpen;

if (shouldAnimate && !isTransitioning) {
setIsTransitioning(true);
// TODO: type === 'open' ? animationInTiming : animationOutTiming,
}
};

@@ -131,7 +130,7 @@ function ReactNativeModal(incomingProps: ModalProps) {
props.onModalWillShow();
}
setIsVisibleState(true);
handleTransition('open');
handleTransition();
};

const close = () => {
@@ -148,7 +147,7 @@ function ReactNativeModal(incomingProps: ModalProps) {
}

setIsVisibleState(false);
handleTransition('close');
handleTransition();
};

useEffect(() => {
@@ -191,17 +190,6 @@ function ReactNativeModal(incomingProps: ModalProps) {

const computedStyle: Array<StyleProp<ViewStyle>> = [{margin: getDeviceWidth() * 0.05}, styles.content, style];

let panPosition: StyleProp<ViewStyle> = {};
if (isSwappable && panResponder) {
if (useNativeDriver) {
panPosition = {
transform: [{translateX: Xoffset.value}, {translateY: Yoffset.value}],
};
} else {
panPosition = pan.getLayout();
}
}

const containerView = (
<Container
animationIn={animationIn}
32 changes: 19 additions & 13 deletions src/components/Modal/ReactNativeModal/panResponders.ts
Original file line number Diff line number Diff line change
@@ -6,14 +6,26 @@ import {calcDistancePercentage, createAnimationEventForSwipe, getAccDistancePerD
import type {AnimationEvent, Direction, GestureResponderEvent} from './types';
import type ModalProps from './types';

function handleSwipe(swipeDirection: Direction, dx: number, dy: number, Xoffset: SharedValue<number>, Yoffset: SharedValue<number>) {
if (swipeDirection === 'right' && dx > 0) {
function handleSwipe(dx: number, dy: number, Xoffset: SharedValue<number>, Yoffset: SharedValue<number>, swipeDirection?: Direction | Direction[]) {
if (!swipeDirection) {
return;
}
const directions = Array.isArray(swipeDirection) ? swipeDirection : [swipeDirection];

if (directions.includes('right') && dx > 0) {
// eslint-disable-next-line no-param-reassign
Xoffset.value = dx;
} else if (swipeDirection === 'left' && dx < 0) {
}
if (directions.includes('left') && dx < 0) {
// eslint-disable-next-line no-param-reassign
Xoffset.value = dx;
} else if (swipeDirection === 'up' && dy < 0) {
}
if (directions.includes('up') && dy < 0) {
// eslint-disable-next-line no-param-reassign
Yoffset.value = dy;
} else if (swipeDirection === 'down' && dy > 0) {
}
if (directions.includes('down') && dy > 0) {
// eslint-disable-next-line no-param-reassign
Yoffset.value = dy;
}
}
@@ -54,9 +66,6 @@ const onMoveShouldSetPanResponder = (
pan: Animated.ValueXY,
) => {
return (evt: GestureResponderEvent, gestureState: PanResponderGestureState) => {
console.log('______________-');
console.log(pan.getTranslateTransform());
console.log('______________-');
if (!shouldPropagateSwipe(evt, gestureState, props.propagateSwipe)) {
const shouldSetPanResponder = Math.abs(gestureState.dx) >= props.panResponderThreshold || Math.abs(gestureState.dy) >= props.panResponderThreshold;
if (shouldSetPanResponder && props.onSwipeStart) {
@@ -100,13 +109,10 @@ const onPanResponderMove = (
deviceWidth: number,
xOffset: SharedValue<number>,
yOffset: SharedValue<number>,
swipeDirection: Direction,
swipeDirection?: Direction | Direction[],
) => {
return (evt: GestureResponderEvent, gestureState: PanResponderGestureState) => {
console.log('______________-');
console.log(swipeDirection);
console.log('______________-');
handleSwipe(swipeDirection, gestureState.dx, gestureState.dy, xOffset, yOffset);
handleSwipe(gestureState.dx, gestureState.dy, xOffset, yOffset, swipeDirection);
const currentSwipingDirection = currentSwipingDirectionRef.current;
if (!currentSwipingDirection) {
if (gestureState.dx === 0 && gestureState.dy === 0) {
14 changes: 13 additions & 1 deletion src/components/Modal/ReactNativeModal/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type {ReactNode} from 'react';
import type {NativeSyntheticEvent, NativeTouchEvent, PanResponderGestureState, StyleProp, ViewProps, ViewStyle} from 'react-native';
import type {SharedValue} from 'react-native-reanimated';

type Orientation = 'portrait' | 'portrait-upside-down' | 'landscape' | 'landscape-left' | 'landscape-right';

@@ -162,10 +163,21 @@ type ModalProps = ViewProps & {
supportedOrientations?: Orientation[];
};

type ContainerProps = {
/** This function is called by open animation callback */
onOpenCallBack: () => void;

/** This function is called by close animation callback */
onCloseCallBack: () => void;

/** Position animated by pan gesture */
panPosition?: {translateX: SharedValue<number>; translateY: SharedValue<number>};
};

type GestureResponderEvent = NativeSyntheticEvent<NativeTouchEvent>;

// eslint-disable-next-line @typescript-eslint/no-explicit-any
type AnimationEvent = (...args: any[]) => void;

export default ModalProps;
export type {GestureResponderEvent, AnimationEvent, Direction, Orientation};
export type {GestureResponderEvent, AnimationEvent, Direction, Orientation, ContainerProps};
2 changes: 2 additions & 0 deletions src/components/Search/SearchRouter/SearchRouterModal.tsx
Original file line number Diff line number Diff line change
@@ -22,6 +22,8 @@ function SearchRouterModal() {
propagateSwipe
shouldHandleNavigationBack={Browser.isMobileChrome()}
onClose={closeSearchRouter}
swipeDirection="right"
swipeThreshold={300}
>
{isSearchRouterDisplayed && (
<FocusTrapForModal active={isSearchRouterDisplayed}>