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

Mobile: Accessibility: Improve setting control accessibility (#11358)

This commit is contained in:
Henry Heino 2024-11-09 04:46:16 -08:00 committed by GitHub
parent 1e21fc242b
commit 4d5b1ce5fd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 27 additions and 7 deletions

View File

@ -23,6 +23,7 @@ interface DropdownProps {
headerStyle?: TextStyle;
itemStyle?: TextStyle;
disabled?: boolean;
accessibilityHint?: string;
labelTransform?: 'trim';
items: DropdownListItem[];
@ -169,6 +170,7 @@ class Dropdown extends Component<DropdownProps, DropdownState> {
<TouchableOpacity
style={itemWrapperStyle}
accessibilityRole="menuitem"
accessibilityState={{ selected: item.value === this.props.selectedValue }}
key={key}
onPress={() => {
this.onCloseList();
@ -209,12 +211,19 @@ class Dropdown extends Component<DropdownProps, DropdownState> {
style={headerWrapperStyle}
disabled={this.props.disabled}
onPress={this.onOpenList}
role='button'
accessibilityRole='button'
accessibilityHint={[this.props.accessibilityHint, _('Opens dropdown')].join(' ')}
>
<Text ellipsizeMode="tail" numberOfLines={1} style={headerStyle}>
{headerLabel}
</Text>
<Text style={headerArrowStyle}>{'▼'}</Text>
<Text
style={headerArrowStyle}
aria-hidden={true}
importantForAccessibility='no'
accessibilityElementsHidden={true}
accessibilityRole='image'
>{'▼'}</Text>
</TouchableOpacity>
{this.state.listVisible ? null : this.props.coverableChildrenRight}
</View>
@ -237,11 +246,13 @@ class Dropdown extends Component<DropdownProps, DropdownState> {
<View
accessibilityRole='menu'
style={wrapperStyle}>
style={wrapperStyle}
>
<FlatList
ref={this.onListLoad}
style={itemListStyle}
data={this.props.items}
extraData={this.props.selectedValue}
renderItem={itemRenderer}
getItemLayout={(_data, index) => ({
length: itemHeight,

View File

@ -10,6 +10,7 @@ import SettingsToggle from './SettingsToggle';
import FileSystemPathSelector from './FileSystemPathSelector';
import shim from '@joplin/lib/shim';
import { themeStyle } from '../../global-style';
import { useId } from 'react';
interface Props {
settingId: string;
@ -39,16 +40,19 @@ const SettingComponent: React.FunctionComponent<Props> = props => {
const descriptionComp = !settingDescription ? null : <Text style={styleSheet.settingDescriptionText}>{settingDescription}</Text>;
const containerStyle = props.styles.getContainerStyle(!!settingDescription);
const labelId = useId();
if (md.isEnum) {
const value = props.value?.toString();
const items = Setting.enumOptionsToValueLabels(md.options(), md.optionsOrder ? md.optionsOrder() : []);
const label = md.label();
return (
<View key={props.settingId} style={{ flexDirection: 'column', borderBottomWidth: 1, borderBottomColor: theme.dividerColor }}>
<View style={containerStyle}>
<Text key="label" style={styleSheet.settingText}>
{md.label()}
{label}
</Text>
<Dropdown
key="control"
@ -69,6 +73,7 @@ const SettingComponent: React.FunctionComponent<Props> = props => {
onValueChange={(itemValue: string) => {
void props.updateSettingValue(props.settingId, itemValue);
}}
accessibilityHint={label}
/>
</View>
{descriptionComp}
@ -90,6 +95,7 @@ const SettingComponent: React.FunctionComponent<Props> = props => {
const unitLabel = md.unitLabel ? md.unitLabel(props.value) : props.value;
const minimum = 'minimum' in md ? md.minimum : 0;
const maximum = 'maximum' in md ? md.maximum : 10;
const label = md.label();
// Note: Do NOT add the minimumTrackTintColor and maximumTrackTintColor props
// on the Slider as they are buggy and can crash the app on certain devices.
@ -97,8 +103,8 @@ const SettingComponent: React.FunctionComponent<Props> = props => {
// https://github.com/react-native-community/react-native-slider/issues/161
return (
<View key={props.settingId} style={styleSheet.settingContainer}>
<Text key="label" style={styleSheet.settingText}>
{md.label()}
<Text key="label" style={styleSheet.settingText} nativeID={labelId}>
{label}
</Text>
<View style={{ display: 'flex', flexDirection: 'row', alignItems: 'center', flex: 1 }}>
<Text style={styleSheet.sliderUnits}>{unitLabel}</Text>
@ -110,6 +116,7 @@ const SettingComponent: React.FunctionComponent<Props> = props => {
maximumValue={maximum}
value={props.value}
onValueChange={newValue => void props.updateSettingValue(props.settingId, newValue)}
accessibilityHint={label}
/>
</View>
</View>
@ -129,7 +136,7 @@ const SettingComponent: React.FunctionComponent<Props> = props => {
return (
<View key={props.settingId} style={{ flexDirection: 'column', borderBottomWidth: 1, borderBottomColor: theme.dividerColor }}>
<View key={props.settingId} style={containerStyle}>
<Text key="label" style={styleSheet.settingText}>
<Text key="label" style={styleSheet.settingText} nativeID={labelId}>
{md.label()}
</Text>
<TextInput
@ -143,6 +150,7 @@ const SettingComponent: React.FunctionComponent<Props> = props => {
value={props.value}
onChangeText={(newValue: string) => void props.updateSettingValue(props.settingId, newValue)}
secureTextEntry={!!md.secure}
aria-labelledby={labelId}
/>
</View>
{descriptionComp}

View File

@ -36,6 +36,7 @@ const SettingsToggle: FunctionComponent<Props> = props => {
trackColor={{ false: theme.dividerColor }}
value={props.value}
onValueChange={(value: boolean) => void props.updateSettingValue(props.settingId, value)}
accessibilityHint={props.label}
/>
</View>
{props.description}