Skip to content

Commit d377d5d

Browse files
Merge branch 'main' into off/873-close-db-connection-before-navigating-between-pages
2 parents c2b5e41 + cd52b80 commit d377d5d

5 files changed

Lines changed: 126 additions & 172 deletions

File tree

packages/pluggableWidgets/bottom-sheet-native/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66

77
## [Unreleased]
88

9+
### Fixed
10+
11+
- Fixed flickering issue on Android when opening bottom sheet (both basic and custom render types).
12+
- Improved backdrop animation with smooth fade-in/fade-out transitions.
13+
914
## [5.3.0] - 2026-6-10
1015

1116
### Changed

packages/pluggableWidgets/bottom-sheet-native/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "bottom-sheet-native",
33
"widgetName": "BottomSheet",
4-
"version": "5.3.0",
4+
"version": "5.3.1",
55
"license": "Apache-2.0",
66
"repository": {
77
"type": "git",
Lines changed: 56 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { ReactElement, ReactNode, useCallback, useEffect, useMemo, useRef, useState } from "react";
2-
import { Dimensions, LayoutChangeEvent, Modal, Pressable } from "react-native";
1+
import { ReactElement, ReactNode, useCallback, useRef, useState } from "react";
2+
import { Modal, Pressable, useWindowDimensions } from "react-native";
33
import BottomSheet, {
44
BottomSheetBackdrop,
55
BottomSheetBackdropProps,
@@ -16,36 +16,50 @@ interface CustomModalSheetProps {
1616

1717
export const CustomModalSheet = (props: CustomModalSheetProps): ReactElement => {
1818
const bottomSheetRef = useRef<BottomSheet>(null);
19-
const [contentHeight, setContentHeight] = useState(0);
20-
const [currentStatus, setCurrentStatus] = useState(false);
19+
const { height: windowHeight } = useWindowDimensions();
2120

22-
const isAvailable = props.triggerAttribute && props.triggerAttribute.status === ValueStatus.Available;
21+
const externalOpen =
22+
props.triggerAttribute?.status === ValueStatus.Available && props.triggerAttribute.value === true;
2323

24-
const isOpen =
25-
props.triggerAttribute &&
26-
props.triggerAttribute.status === ValueStatus.Available &&
27-
props.triggerAttribute.value;
24+
const [mounted, setMounted] = useState(externalOpen);
25+
const [ready, setReady] = useState(false);
26+
const didOpenRef = useRef(false);
2827

29-
const onContentLayoutHandler = useCallback(
30-
(event: LayoutChangeEvent): void => {
31-
const layoutHeight = event.nativeEvent.layout.height;
32-
if (layoutHeight > 0 && layoutHeight !== contentHeight) {
33-
setContentHeight(layoutHeight);
34-
}
35-
},
36-
[contentHeight]
37-
);
28+
if (externalOpen && !mounted) {
29+
setMounted(true);
30+
}
3831

3932
const close = useCallback(() => {
4033
bottomSheetRef.current?.close();
4134
}, []);
4235

36+
const handleModalShow = useCallback(() => {
37+
setReady(true);
38+
}, []);
39+
40+
const handleChange = useCallback(
41+
(index: number) => {
42+
if (index === 0) {
43+
didOpenRef.current = true;
44+
return;
45+
}
46+
47+
if (index === -1 && didOpenRef.current) {
48+
didOpenRef.current = false;
49+
setReady(false);
50+
props.triggerAttribute?.setValue(false);
51+
setMounted(false);
52+
}
53+
},
54+
[props.triggerAttribute]
55+
);
56+
4357
const renderBackdrop = useCallback(
4458
(backdropProps: BottomSheetBackdropProps) => (
4559
<Pressable style={{ flex: 1 }} onPress={close}>
4660
<BottomSheetBackdrop
4761
{...backdropProps}
48-
pressBehavior={"close"}
62+
pressBehavior="close"
4963
opacity={0.3}
5064
appearsOnIndex={0}
5165
disappearsOnIndex={-1}
@@ -55,72 +69,32 @@ export const CustomModalSheet = (props: CustomModalSheetProps): ReactElement =>
5569
[close]
5670
);
5771

58-
const snapPoints = useMemo(() => {
59-
if (contentHeight === 0) {
60-
return [1]; // During measurement
61-
}
62-
63-
// Use actual measured content height, cap at 90% screen
64-
const maxHeight = Dimensions.get("screen").height * 0.9;
65-
const snapHeight = Math.min(contentHeight, maxHeight);
66-
return [snapHeight];
67-
}, [contentHeight]);
68-
69-
const handleSheetChanges = useCallback(
70-
(index: number) => {
71-
if (!isAvailable) {
72-
return;
73-
}
74-
75-
const hasClosed = index === -1;
76-
if (hasClosed && props.triggerAttribute?.value) {
77-
props.triggerAttribute?.setValue(false);
78-
setCurrentStatus(false);
79-
}
80-
},
81-
[isAvailable, props.triggerAttribute]
82-
);
83-
84-
useEffect(() => {
85-
if (!isAvailable) {
86-
return;
87-
}
88-
89-
const shouldBeOpen = props.triggerAttribute?.value === true;
90-
91-
if (shouldBeOpen && !currentStatus) {
92-
requestAnimationFrame(() => {
93-
setCurrentStatus(true);
94-
});
95-
} else if (!shouldBeOpen && currentStatus) {
96-
bottomSheetRef.current?.close();
97-
setCurrentStatus(false);
98-
}
99-
}, [props.triggerAttribute?.value, currentStatus, isAvailable]);
72+
const maxHeight = windowHeight * 0.9;
10073

10174
return (
102-
<Modal onRequestClose={close} transparent visible={!!isOpen}>
103-
<BottomSheet
104-
ref={bottomSheetRef}
105-
index={isOpen ? 0 : -1}
106-
snapPoints={snapPoints}
107-
onClose={() => handleSheetChanges(-1)}
108-
onChange={handleSheetChanges}
109-
backdropComponent={renderBackdrop}
110-
style={[props.styles.modal]}
111-
backgroundStyle={props.styles.container}
112-
enablePanDownToClose={false}
113-
handleComponent={null}
114-
handleStyle={{ display: "none" }}
115-
>
116-
<BottomSheetScrollView
117-
style={[{ flex: 1 }]}
118-
contentContainerStyle={{ paddingBottom: 16 }}
119-
onLayout={onContentLayoutHandler}
75+
<Modal transparent animationType="none" visible={mounted} onRequestClose={close} onShow={handleModalShow}>
76+
{ready && (
77+
<BottomSheet
78+
ref={bottomSheetRef}
79+
index={0}
80+
animateOnMount
81+
enableDynamicSizing
82+
maxDynamicContentSize={maxHeight}
83+
containerHeight={windowHeight}
84+
enablePanDownToClose
85+
onChange={handleChange}
86+
onClose={() => handleChange(-1)}
87+
backdropComponent={renderBackdrop}
88+
style={[props.styles.modal]}
89+
backgroundStyle={props.styles.container}
90+
handleComponent={null}
91+
handleStyle={{ display: "none" }}
12092
>
121-
{props.content}
122-
</BottomSheetScrollView>
123-
</BottomSheet>
93+
<BottomSheetScrollView style={[{ flex: 1 }]} contentContainerStyle={{ paddingBottom: 16 }}>
94+
{props.content}
95+
</BottomSheetScrollView>
96+
</BottomSheet>
97+
)}
12498
</Modal>
12599
);
126100
};

0 commit comments

Comments
 (0)