Files
CBS-Mobile-App/src/components/BottomSheet/index.tsx
T

113 lines
2.9 KiB
TypeScript

import React, { useEffect, useRef } from 'react';
import {
Animated,
Keyboard,
KeyboardAvoidingView,
Modal,
Platform,
Pressable,
ScrollView,
StyleSheet,
Text,
TouchableWithoutFeedback,
View,
} from 'react-native';
import { useTheme, fontFamily } from '../../theme';
interface BottomSheetProps {
visible: boolean;
title?: string;
onClose: () => void;
children: React.ReactNode;
}
export const BottomSheet = ({ visible, title, onClose, children }: BottomSheetProps) => {
const theme = useTheme();
const translateY = useRef(new Animated.Value(320)).current;
useEffect(() => {
Animated.timing(translateY, {
toValue: visible ? 0 : 320,
duration: 220,
useNativeDriver: true,
}).start();
}, [translateY, visible]);
const handleBackdropPress = () => {
Keyboard.dismiss();
onClose();
};
return (
<Modal animationType="fade" transparent visible={visible} onRequestClose={onClose}>
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
style={styles.flex}
keyboardVerticalOffset={Platform.OS === 'ios' ? 10 : 0}
>
<TouchableWithoutFeedback onPress={handleBackdropPress}>
<View style={[styles.backdrop, { backgroundColor: theme.colors.overlay }]}>
<TouchableWithoutFeedback onPress={() => {}}>
<Animated.View
style={[
styles.sheet,
{
backgroundColor: theme.colors.backgroundElevated,
borderTopLeftRadius: theme.radius.lg,
borderTopRightRadius: theme.radius.lg,
transform: [{ translateY }],
},
]}
>
<View style={[styles.handle, { backgroundColor: theme.colors.cardBorder }]} />
{title ? (
<Text style={[styles.title, { color: theme.colors.textPrimary }]}>{title}</Text>
) : null}
<ScrollView
keyboardShouldPersistTaps="handled"
showsVerticalScrollIndicator={false}
bounces={false}
contentContainerStyle={styles.sheetScroll}
>
{children}
</ScrollView>
</Animated.View>
</TouchableWithoutFeedback>
</View>
</TouchableWithoutFeedback>
</KeyboardAvoidingView>
</Modal>
);
};
const styles = StyleSheet.create({
flex: {
flex: 1,
},
backdrop: {
flex: 1,
justifyContent: 'flex-end',
},
sheet: {
paddingHorizontal: 20,
paddingTop: 14,
paddingBottom: 28,
gap: 12,
maxHeight: '80%',
},
sheetScroll: {
flexGrow: 1,
},
handle: {
width: 42,
height: 4,
borderRadius: 999,
alignSelf: 'center',
},
title: {
fontSize: 18,
fontFamily: fontFamily.bold,
},
});