fix: improve modal behavior on web and Android scrolling

- Restructure ModalBase to use absolute-positioned backdrop behind card
  content, fixing modal stacking issues on web (React Native Web portals)
- Hide EventOverlay when DeleteEventModal is open to prevent z-index
  conflicts on web
- Add nestedScrollEnabled to CardBase ScrollView for Android
- Use TouchableOpacity with delayPressIn in EventCard for scroll-friendly
  touch handling
- Keep eventToDelete state stable during modal fade-out to prevent
  content flash between recurring/single variants
- Fix German umlauts in DeleteEventModal
This commit is contained in:
2026-01-25 22:38:37 +01:00
parent 726334c155
commit 4575483940
6 changed files with 40 additions and 25 deletions

View File

@@ -84,7 +84,10 @@ export const CardBase = ({
{/* Content */}
{scrollable ? (
<ScrollView style={{ maxHeight: maxContentHeight }}>
<ScrollView
style={{ maxHeight: maxContentHeight }}
nestedScrollEnabled={true}
>
{contentElement}
</ScrollView>
) : (

View File

@@ -77,7 +77,7 @@ export const DeleteEventModal = ({
// Non-recurring event: simple confirmation
<View>
<Text className="text-base mb-4" style={{ color: theme.textPrimary }}>
Moechtest du diesen Termin wirklich loeschen?
Möchtest du diesen Termin wirklich löschen?
</Text>
<Pressable
onPress={() => onConfirm("all")}
@@ -90,7 +90,7 @@ export const DeleteEventModal = ({
className="font-medium text-base text-center"
style={{ color: theme.buttonText }}
>
Loeschen
Löschen
</Text>
</Pressable>
</View>

View File

@@ -1,4 +1,4 @@
import { View, Pressable } from "react-native";
import { View, TouchableOpacity } from "react-native";
import { ExpandedEvent } from "@calchat/shared";
import { Feather } from "@expo/vector-icons";
import { useThemeStore } from "../stores/ThemeStore";
@@ -21,10 +21,12 @@ export const EventCard = ({ event, onEdit, onDelete }: EventCardProps) => {
description={event.description}
isRecurring={event.isRecurring}
>
{/* Action buttons */}
{/* Action buttons - TouchableOpacity with delayPressIn allows ScrollView to detect scroll gestures */}
<View className="flex-row justify-end mt-3 gap-3">
<Pressable
<TouchableOpacity
onPress={onEdit}
delayPressIn={100}
activeOpacity={0.7}
className="w-10 h-10 rounded-full items-center justify-center"
style={{
borderWidth: 1,
@@ -32,9 +34,11 @@ export const EventCard = ({ event, onEdit, onDelete }: EventCardProps) => {
}}
>
<Feather name="edit-2" size={18} color={theme.textPrimary} />
</Pressable>
<Pressable
</TouchableOpacity>
<TouchableOpacity
onPress={onDelete}
delayPressIn={100}
activeOpacity={0.7}
className="w-10 h-10 rounded-full items-center justify-center"
style={{
borderWidth: 1,
@@ -42,7 +46,7 @@ export const EventCard = ({ event, onEdit, onDelete }: EventCardProps) => {
}}
>
<Feather name="trash-2" size={18} color={theme.textPrimary} />
</Pressable>
</TouchableOpacity>
</View>
</EventCardBase>
</View>

View File

@@ -1,4 +1,4 @@
import { Modal, Pressable } from "react-native";
import { Modal, Pressable, View } from "react-native";
import { ReactNode } from "react";
import { useThemeStore } from "../stores/ThemeStore";
import { CardBase } from "./CardBase";
@@ -36,19 +36,21 @@ export const ModalBase = ({
animationType="fade"
onRequestClose={onClose}
>
<Pressable
className="flex-1 justify-center items-center"
style={{ backgroundColor: "rgba(0,0,0,0.5)" }}
onPress={onClose}
>
<View className="flex-1 justify-center items-center">
{/* Backdrop - absolute positioned behind the card */}
<Pressable
className="absolute inset-0"
style={{ backgroundColor: "rgba(0,0,0,0.5)" }}
onPress={onClose}
/>
{/* Card content - on top, naturally blocks touches to backdrop */}
<View
className="w-11/12 rounded-2xl overflow-hidden"
style={{
backgroundColor: theme.primeBg,
borderWidth: 4,
borderColor: theme.borderPrimary,
}}
onPress={(e) => e.stopPropagation()}
>
<CardBase
title={title}
@@ -65,8 +67,8 @@ export const ModalBase = ({
>
{children}
</CardBase>
</Pressable>
</Pressable>
</View>
</View>
</Modal>
);
};