Skip to content

Commit 776c7c4

Browse files
Adds height prop change responder
1 parent a678f54 commit 776c7c4

File tree

4 files changed

+49
-7
lines changed

4 files changed

+49
-7
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ A cross platform, lightweight, pure JS implementation (no dependencies) of botto
1515
- :last_quarter_moon: **Light and Dark mode** supported by default, and responds to changes automatically.
1616
- :arrow_up_down: **Draggable**: You can drag to close once you cross the close threshold, and a drag marker will show to indicate this.
1717
- :round_pushpin: **Closeable using background**: By tapping on the background behind the sheet, the sheet will be closed.
18-
- :arrow_backward: **Closeable using Android back button**: will automatically close the modal.
18+
- :arrow_backward: **Closeable using Android back button**: will automatically close the bottmo sheet.
19+
- :monocle_face: **Responds to height changes**: if the `height` prop changes, the bottom sheet will change height while open.
1920
- :art: **Customisable and easy to style** with lots of prop options.
2021
- :speech_balloon: **Callbacks galore**: Lots of easy to use callbacks, such as `onOpenStart` and `onOpenFinish`.
2122
- :blue_book: **TypeScript** support - fully written in TypeScript.

example/src/App.tsx

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,25 @@
1-
import React, { useRef } from 'react';
1+
import React, { useRef, useState } from 'react';
22
import { StyleSheet, View, TouchableOpacity, Text, useColorScheme } from 'react-native';
33
import { BottomSheet, BottomSheetRef } from 'react-native-sheet';
44

55
export default function App() {
66
const colorScheme = useColorScheme() || 'light';
77
const isDarkMode = colorScheme === 'dark';
88
const bottomSheet = useRef<BottomSheetRef>(null);
9+
const [height, setHeight] = useState(400);
910

1011
return (
1112
<View style={[styles.container, { backgroundColor: isDarkMode ? '#0f0f0f' : '#ffffff' }]}>
12-
<BottomSheet height={400} ref={bottomSheet} contentContainerStyle={styles.bottomSheetContainer}>
13+
<BottomSheet height={height} ref={bottomSheet} contentContainerStyle={styles.bottomSheetContainer}>
1314
<Text style={{ color: isDarkMode ? '#ffffff' : '#222222' }}>Your content here</Text>
14-
<TouchableOpacity style={styles.button} onPress={() => bottomSheet.current?.hide()}>
15-
<Text style={styles.buttonText}>Close</Text>
16-
</TouchableOpacity>
15+
<View>
16+
<TouchableOpacity style={styles.button} onPress={() => setHeight(currentHeight => (currentHeight === 400 ? 700 : 400))}>
17+
<Text style={styles.buttonText}>Change height</Text>
18+
</TouchableOpacity>
19+
<TouchableOpacity style={styles.button} onPress={() => bottomSheet.current?.hide()}>
20+
<Text style={styles.buttonText}>Close</Text>
21+
</TouchableOpacity>
22+
</View>
1723
</BottomSheet>
1824
<TouchableOpacity onPress={() => bottomSheet.current?.show()}>
1925
<Text style={{ color: isDarkMode ? '#ffffff' : '#222222' }}>Open Bottom Sheet</Text>

src/__tests__/BottomSheet.test.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,4 +173,26 @@ describe('BottomSheet', () => {
173173
expect(onCloseStart).toHaveBeenCalledTimes(1);
174174
await waitFor(() => expect(onCloseFinish).toHaveBeenCalledTimes(1));
175175
});
176+
177+
it('should respond to height changes', () => {
178+
const ref = createRef<BottomSheetRef>();
179+
const { getByTestId, rerender } = render(
180+
<BottomSheet ref={ref} height={400}>
181+
{null}
182+
</BottomSheet>
183+
);
184+
act(() => {
185+
ref.current?.show();
186+
});
187+
188+
expect(getByTestId('animated-view')).toHaveStyle({ height: 400 });
189+
190+
rerender(
191+
<BottomSheet ref={ref} height={600}>
192+
{null}
193+
</BottomSheet>
194+
);
195+
196+
expect(getByTestId('animated-view')).toHaveStyle({ height: 600 });
197+
});
176198
});

src/features/BottomSheet/BottomSheet.tsx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { memo, useMemo, useState, useRef, useImperativeHandle, useCallback, forwardRef, ReactNode } from 'react';
1+
import React, { memo, useMemo, useState, useRef, useImperativeHandle, useCallback, forwardRef, ReactNode, useEffect } from 'react';
22
import { Platform, View, Modal, TouchableOpacity, Animated, PanResponder, ViewStyle, useColorScheme } from 'react-native';
33
import { styles } from './styles';
44

@@ -99,6 +99,7 @@ export const BottomSheet = memo(
9999
[animatedHeight, closeTime, height, onCloseFinish, onCloseStart, onOpenFinish, onOpenStart, openTime, pan]
100100
);
101101

102+
// Respond to pan changes
102103
const panResponder = useRef(
103104
PanResponder.create({
104105
onStartShouldSetPanResponder: () => true,
@@ -124,11 +125,22 @@ export const BottomSheet = memo(
124125
})
125126
).current;
126127

128+
// If `height` prop changes, respond and change to new height immediately
129+
useEffect(() => {
130+
Animated.timing(animatedHeight, {
131+
toValue: height,
132+
duration: 0,
133+
useNativeDriver: false
134+
}).start();
135+
}, [height]);
136+
137+
// Expose specific methods on hook
127138
useImperativeHandle(ref, () => ({
128139
show: () => setModalVisibility(true),
129140
hide: () => setModalVisibility(false)
130141
}));
131142

143+
// Return nothing if not visible
132144
if (!visible) return null;
133145

134146
return (
@@ -158,6 +170,7 @@ export const BottomSheet = memo(
158170
},
159171
sheetStyle
160172
]}
173+
testID='animated-view'
161174
>
162175
{isDraggable && showDragIcon && (
163176
<View style={styles.draggableContainer}>

0 commit comments

Comments
 (0)