You've already forked joplin
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:
@@ -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}>
|
||||||
|
|||||||
Reference in New Issue
Block a user