1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-11-26 22:41:17 +02:00

Mobile: Accessibility: Make default modal close button accessible (#11957)

This commit is contained in:
Henry Heino
2025-03-15 06:20:11 -07:00
committed by GitHub
parent b042395fd1
commit c8b01d11d6

View File

@@ -1,11 +1,12 @@
import * as React from 'react'; import * as React from 'react';
import { RefObject, useCallback, useMemo, useRef, useState } from 'react'; import { RefObject, useCallback, useMemo, useRef, useState } from 'react';
import { GestureResponderEvent, Modal, ModalProps, Platform, ScrollView, StyleSheet, View, ViewStyle, useWindowDimensions } from 'react-native'; import { GestureResponderEvent, Modal, ModalProps, Platform, Pressable, ScrollView, StyleSheet, View, ViewStyle, useWindowDimensions } from 'react-native';
import { hasNotch } from 'react-native-device-info'; import { hasNotch } from 'react-native-device-info';
import FocusControl from './accessibility/FocusControl/FocusControl'; import FocusControl from './accessibility/FocusControl/FocusControl';
import { msleep, Second } from '@joplin/utils/time'; import { msleep, Second } from '@joplin/utils/time';
import useAsyncEffect from '@joplin/lib/hooks/useAsyncEffect'; import useAsyncEffect from '@joplin/lib/hooks/useAsyncEffect';
import { ModalState } from './accessibility/FocusControl/types'; import { ModalState } from './accessibility/FocusControl/types';
import { _ } from '@joplin/lib/locale';
interface ModalElementProps extends ModalProps { interface ModalElementProps extends ModalProps {
children: React.ReactNode; children: React.ReactNode;
@@ -53,6 +54,13 @@ const useStyles = (hasScrollView: boolean, backgroundColor: string|undefined) =>
// This makes it possible to vertically center the content of scrollable modals. // This makes it possible to vertically center the content of scrollable modals.
flexGrow: 1, flexGrow: 1,
}, },
dismissButton: {
position: 'absolute',
bottom: 0,
height: 12,
width: '100%',
zIndex: -1,
},
}); });
}, [hasScrollView, isLandscape, backgroundColor]); }, [hasScrollView, isLandscape, backgroundColor]);
}; };
@@ -126,12 +134,24 @@ const ModalElement: React.FC<ModalElementProps> = ({
containerRef.current = containerComponent; containerRef.current = containerComponent;
const { onShouldBackgroundCaptureTouch, onBackgroundTouchFinished } = useBackgroundTouchListeners(modalProps.onRequestClose, containerRef); const { onShouldBackgroundCaptureTouch, onBackgroundTouchFinished } = useBackgroundTouchListeners(modalProps.onRequestClose, containerRef);
// A close button for accessibility tools. Since iOS accessibility focus order is based on the position
// of the element on the screen, the close button is placed after the modal content, rather than behind.
const closeButton = modalProps.onRequestClose ? <Pressable
style={styles.dismissButton}
onPress={modalProps.onRequestClose}
accessibilityLabel={_('Close dialog')}
accessibilityRole='button'
/> : null;
const contentAndBackdrop = <View const contentAndBackdrop = <View
ref={setContainerComponent} ref={setContainerComponent}
style={styles.modalBackground} style={styles.modalBackground}
onStartShouldSetResponder={onShouldBackgroundCaptureTouch} onStartShouldSetResponder={onShouldBackgroundCaptureTouch}
onResponderRelease={onBackgroundTouchFinished} onResponderRelease={onBackgroundTouchFinished}
>{content}</View>; >
{content}
{closeButton}
</View>;
return ( return (
<FocusControl.ModalWrapper state={modalStatus}> <FocusControl.ModalWrapper state={modalStatus}>