1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-01-05 12:50:29 +02:00

iOS: Fixes #7553: Fix Dropdown accessibility (#7564)

This commit is contained in:
Henry Heino 2023-01-10 09:13:32 -08:00 committed by GitHub
parent 6bb52d5ad6
commit 0cd2fd660d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,6 +1,7 @@
const React = require('react'); const React = require('react');
import { TouchableOpacity, TouchableWithoutFeedback, Dimensions, Text, Modal, View, LayoutRectangle, ViewStyle, TextStyle } from 'react-native'; import { TouchableOpacity, TouchableWithoutFeedback, Dimensions, Text, Modal, View, LayoutRectangle, ViewStyle, TextStyle } from 'react-native';
import { Component } from 'react'; import { Component } from 'react';
import { _ } from '@joplin/lib/locale';
const { ItemList } = require('./ItemList.js'); const { ItemList } = require('./ItemList.js');
type ValueType = string; type ValueType = string;
@ -58,6 +59,7 @@ class Dropdown extends Component<DropdownProps, DropdownState> {
const items = this.props.items; const items = this.props.items;
const itemHeight = 60; const itemHeight = 60;
const windowHeight = Dimensions.get('window').height - 50; const windowHeight = Dimensions.get('window').height - 50;
const windowWidth = Dimensions.get('window').width;
// Dimensions doesn't return quite the right dimensions so leave an extra gap to make // Dimensions doesn't return quite the right dimensions so leave an extra gap to make
// sure nothing is off screen. // sure nothing is off screen.
@ -66,11 +68,20 @@ class Dropdown extends Component<DropdownProps, DropdownState> {
const maxListTop = windowHeight - listHeight; const maxListTop = windowHeight - listHeight;
const listTop = Math.min(maxListTop, this.state.headerSize.y + this.state.headerSize.height); const listTop = Math.min(maxListTop, this.state.headerSize.y + this.state.headerSize.height);
const wrapperStyle = { const wrapperStyle: ViewStyle = {
width: this.state.headerSize.width, width: this.state.headerSize.width,
height: listHeight + 2, // +2 for the border (otherwise it makes the scrollbar appear) height: listHeight + 2, // +2 for the border (otherwise it makes the scrollbar appear)
marginTop: listTop, top: listTop,
marginLeft: this.state.headerSize.x, left: this.state.headerSize.x,
position: 'absolute',
};
const backgroundCloseButtonStyle: ViewStyle = {
position: 'absolute',
top: 0,
left: 0,
height: windowHeight,
width: windowWidth,
}; };
const itemListStyle = Object.assign({}, this.props.itemListStyle ? this.props.itemListStyle : {}, { const itemListStyle = Object.assign({}, this.props.itemListStyle ? this.props.itemListStyle : {}, {
@ -126,6 +137,7 @@ class Dropdown extends Component<DropdownProps, DropdownState> {
return ( return (
<TouchableOpacity <TouchableOpacity
style={itemWrapperStyle} style={itemWrapperStyle}
accessibilityRole="menuitem"
key={key} key={key}
onPress={() => { onPress={() => {
closeList(); closeList();
@ -139,6 +151,22 @@ class Dropdown extends Component<DropdownProps, DropdownState> {
); );
}; };
// Use a separate screen-reader-only button for closing the menu. If we
// allow the background to be focusable, instead, the focus order might be
// incorrect on some devices. For example, the background button might be focused
// when navigating near the middle of the dropdown's list.
const screenReaderCloseMenuButton = (
<TouchableWithoutFeedback
accessibilityRole='button'
onPress={()=> closeList()}
>
<Text style={{
opacity: 0,
height: 0,
}}>{_('Close dropdown')}</Text>
</TouchableWithoutFeedback>
);
return ( return (
<View style={{ flex: 1, flexDirection: 'column' }}> <View style={{ flex: 1, flexDirection: 'column' }}>
<TouchableOpacity <TouchableOpacity
@ -163,12 +191,19 @@ class Dropdown extends Component<DropdownProps, DropdownState> {
}} }}
> >
<TouchableWithoutFeedback <TouchableWithoutFeedback
onPressOut={() => { accessibilityElementsHidden={true}
importantForAccessibility='no-hide-descendants'
onPress={() => {
closeList(); closeList();
}} }}
style={backgroundCloseButtonStyle}
> >
<View style={{ flex: 1 }}> <View style={{ flex: 1 }}/>
<View style={wrapperStyle}> </TouchableWithoutFeedback>
<View
accessibilityRole='menu'
style={wrapperStyle}>
<ItemList <ItemList
style={itemListStyle} style={itemListStyle}
items={this.props.items} items={this.props.items}
@ -176,8 +211,8 @@ class Dropdown extends Component<DropdownProps, DropdownState> {
itemRenderer={itemRenderer} itemRenderer={itemRenderer}
/> />
</View> </View>
</View>
</TouchableWithoutFeedback> {screenReaderCloseMenuButton}
</Modal> </Modal>
</View> </View>
); );