Files
digital-pilates/components/ui/FloatingSelectionCard.tsx
2025-10-14 16:31:19 +08:00

144 lines
3.1 KiB
TypeScript

import { Ionicons } from '@expo/vector-icons';
import { BlurView } from 'expo-blur';
import { GlassView, isLiquidGlassAvailable } from 'expo-glass-effect';
import React from 'react';
import {
Modal,
StyleSheet,
Text,
TouchableOpacity,
View,
} from 'react-native';
interface FloatingSelectionCardProps {
visible: boolean;
onClose: () => void;
title: string;
children: React.ReactNode;
}
export function FloatingSelectionCard({
visible,
onClose,
title,
children
}: FloatingSelectionCardProps) {
const glassAvailable = isLiquidGlassAvailable();
const CloseWrapper = glassAvailable ? GlassView : View;
const closeInnerStyle = [
styles.closeButtonInnerBase,
glassAvailable ? styles.closeButtonInnerGlass : styles.closeButtonInnerFallback,
];
const closeWrapperProps = glassAvailable
? {
glassEffectStyle: 'regular' as const,
tintColor: 'rgba(255,255,255,0.45)',
isInteractive: true,
}
: {};
return (
<Modal
visible={visible}
transparent={true}
animationType="fade"
onRequestClose={onClose}
>
<BlurView intensity={20} tint="dark" style={styles.overlay}>
<TouchableOpacity
style={styles.backdrop}
activeOpacity={1}
onPress={onClose}
/>
<View style={styles.container}>
<BlurView intensity={80} tint="light" style={styles.blurContainer}>
<View style={styles.header}>
<Text style={styles.title}>{title}</Text>
</View>
<View style={styles.content}>
{children}
</View>
</BlurView>
<TouchableOpacity
style={styles.closeButton}
onPress={onClose}
activeOpacity={0.7}
>
<CloseWrapper style={closeInnerStyle} {...closeWrapperProps}>
<Ionicons name="close" size={24} color="#666" />
</CloseWrapper>
</TouchableOpacity>
</View>
</BlurView>
</Modal>
);
}
const styles = StyleSheet.create({
overlay: {
flex: 1,
justifyContent: 'flex-end',
alignItems: 'center',
paddingHorizontal: 20,
},
backdrop: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
},
container: {
alignItems: 'center',
marginBottom: 40,
},
blurContainer: {
borderRadius: 20,
overflow: 'hidden',
backgroundColor: 'rgba(255, 255, 255, 0.95)',
minWidth: 340,
paddingVertical: 20,
paddingHorizontal: 16,
minHeight: 100,
},
header: {
paddingBottom: 20,
alignItems: 'center',
},
title: {
fontSize: 14,
fontWeight: '600',
color: '#636161ff',
},
content: {
alignItems: 'center',
},
closeButton: {
marginTop: 20,
},
closeButtonInnerBase: {
width: 44,
height: 44,
borderRadius: 22,
alignItems: 'center',
justifyContent: 'center',
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.1,
shadowRadius: 4,
elevation: 3,
},
closeButtonInnerGlass: {
},
closeButtonInnerFallback: {
backgroundColor: 'rgba(255, 255, 255, 0.9)',
},
});