fix(client): store accessibility for screenreaders (#42996)

* fix: store accessibility for screenreaders

* Apply suggestions from code review

Co-authored-by: Shaun Hamilton <shauhami020@gmail.com>

* fix: remove old comments

* feat: at short cut announcement when running test

* feat: announce that accesibility mode is turned on

* fix: use Redux values

* Apply suggestions from code review

Co-authored-by: Shaun Hamilton <shauhami020@gmail.com>

* Apply suggestions from Oliver

Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com>

* fix: "rip out redux stuff" and use store instead

* Apply suggestions from code review

Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com>

* Apply suggestions from code review

Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com>

* fix: old use of props

* Update client/src/templates/Challenges/classic/editor.tsx

Co-authored-by: Shaun Hamilton <shauhami020@gmail.com>

Co-authored-by: Shaun Hamilton <shauhami020@gmail.com>
Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com>
pull/43131/head
Sem Bauke 2021-08-06 14:17:17 +02:00 committed by GitHub
parent cbf553639d
commit eccc642d83
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 38 additions and 57 deletions

View File

@ -8,9 +8,7 @@ import {
canFocusEditorSelector,
consoleOutputSelector,
executeChallenge,
inAccessibilityModeSelector,
saveEditorContent,
setAccessibilityMode,
setEditorFocusability,
visibleEditorsSelector,
updateFile
@ -31,7 +29,6 @@ const propTypes = {
executeChallenge: PropTypes.func.isRequired,
ext: PropTypes.string,
fileKey: PropTypes.string,
inAccessibilityMode: PropTypes.bool.isRequired,
initialEditorContent: PropTypes.string,
initialExt: PropTypes.string,
output: PropTypes.arrayOf(PropTypes.string),
@ -40,7 +37,6 @@ const propTypes = {
onResize: PropTypes.func
}),
saveEditorContent: PropTypes.func.isRequired,
setAccessibilityMode: PropTypes.func.isRequired,
setEditorFocusability: PropTypes.func,
theme: PropTypes.string,
title: PropTypes.string,
@ -57,21 +53,12 @@ const mapStateToProps = createSelector(
visibleEditorsSelector,
canFocusEditorSelector,
consoleOutputSelector,
inAccessibilityModeSelector,
isDonationModalOpenSelector,
userSelector,
(
visibleEditors,
canFocus,
output,
accessibilityMode,
open,
{ theme = 'default' }
) => ({
(visibleEditors, canFocus, output, open, { theme = 'default' }) => ({
visibleEditors,
canFocus: open ? false : canFocus,
output,
inAccessibilityMode: accessibilityMode,
theme
})
);
@ -79,7 +66,6 @@ const mapStateToProps = createSelector(
const mapDispatchToProps = {
executeChallenge,
saveEditorContent,
setAccessibilityMode,
setEditorFocusability,
updateFile
};

View File

@ -16,7 +16,7 @@ import React, {
} from 'react';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import store from 'store';
import { Loader } from '../../../components/helpers';
import { userSelector, isDonationModalOpenSelector } from '../../../redux';
import {
@ -27,14 +27,13 @@ import {
ResizePropsType,
TestType
} from '../../../redux/prop-types';
import {
canFocusEditorSelector,
consoleOutputSelector,
executeChallenge,
inAccessibilityModeSelector,
saveEditorContent,
setEditorFocusability,
setAccessibilityMode,
updateFile,
challengeTestsSelector,
submitChallenge
@ -55,13 +54,11 @@ interface EditorProps {
executeChallenge: (isShouldCompletionModalOpen?: boolean) => void;
ext: ExtTypes;
fileKey: FileKeyTypes;
inAccessibilityMode: boolean;
initialEditorContent: string;
initialExt: string;
output: string[];
resizeProps: ResizePropsType;
saveEditorContent: () => void;
setAccessibilityMode: (isAccessible: boolean) => void;
setEditorFocusability: (isFocusable: boolean) => void;
submitChallenge: () => void;
tests: TestType[];
@ -100,21 +97,18 @@ interface EditorPropertyStore {
const mapStateToProps = createSelector(
canFocusEditorSelector,
consoleOutputSelector,
inAccessibilityModeSelector,
isDonationModalOpenSelector,
userSelector,
challengeTestsSelector,
(
canFocus: boolean,
output: string[],
accessibilityMode: boolean,
open,
{ theme = 'default' }: { theme: string },
tests: [{ text: string; testString: string }]
) => ({
canFocus: open ? false : canFocus,
output,
inAccessibilityMode: accessibilityMode,
theme,
tests
})
@ -125,7 +119,6 @@ const mapStateToProps = createSelector(
const mapDispatchToProps = {
executeChallenge,
saveEditorContent,
setAccessibilityMode,
setEditorFocusability,
updateFile,
submitChallenge
@ -297,12 +290,31 @@ const Editor = (props: EditorProps): JSX.Element => {
// TODO this should *probably* be set on focus
editorRef.current = editor;
data.editor = editor;
const storedAccessibilityMode = () => {
const accessibility = store.get('accessibilityMode') as boolean;
if (!accessibility) {
store.set('accessibilityMode', false);
}
// Only able to set the arialabel when accessibility mode is set to true
// Otherwise it gets overwritten by the monaco default aria-label
if (accessibility) {
editor.updateOptions({
ariaLabel:
'Accessibility mode set to true. Press Ctrl+e to disable or press Alt+F1 for more options'
});
}
return accessibility;
};
const accessibilityMode = storedAccessibilityMode();
editor.updateOptions({
accessibilitySupport: props.inAccessibilityMode ? 'on' : 'auto'
accessibilitySupport: accessibilityMode ? 'on' : 'auto'
});
// Users who are using screen readers should not have to move focus from
// the editor to the description every time they open a challenge.
if (props.canFocus && !props.inAccessibilityMode) {
if (props.canFocus && !accessibilityMode) {
// TODO: only one Editor should be calling for focus at once.
editor.focus();
} else focusOnHotkeys();
@ -343,28 +355,18 @@ const Editor = (props: EditorProps): JSX.Element => {
editor.addAction({
id: 'toggle-accessibility',
label: 'Toggle Accessibility Mode',
keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.F1],
keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_E],
run: () => {
const currentAccessibility = props.inAccessibilityMode;
// The store needs to be updated first, as onDidChangeConfiguration is
// called before updateOptions returns
props.setAccessibilityMode(!currentAccessibility);
const currentAccessibility = storedAccessibilityMode();
store.set('accessibilityMode', !currentAccessibility);
editor.updateOptions({
accessibilitySupport: currentAccessibility ? 'auto' : 'on'
accessibilitySupport: storedAccessibilityMode() ? 'on' : 'auto',
});
}
});
editor.onDidFocusEditorWidget(() => props.setEditorFocusability(true));
// This is to persist changes caused by the accessibility tooltip.
editor.onDidChangeConfiguration(event => {
if (
event.hasChanged(monaco.editor.EditorOption.accessibilitySupport) &&
editor.getRawOptions().accessibilitySupport === 'on' &&
!props.inAccessibilityMode
) {
props.setAccessibilityMode(true);
}
});
const editableBoundaries = getEditableRegion();

View File

@ -53,7 +53,12 @@ function ToolPanel({
isMobile ? 'tool-panel-group-mobile' : ''
}`}
>
<Button block={true} bsStyle='primary' onClick={handleRunTests}>
<Button
aria-label='Run the tests use shortcut Ctrl+enter'
block={true}
bsStyle='primary'
onClick={handleRunTests}
>
{isMobile ? t('buttons.run') : t('buttons.run-test')}
</Button>
<Button

View File

@ -41,8 +41,7 @@ export const actionTypes = createTypes(
'moveToTab',
'setEditorFocusability',
'toggleVisibleEditor',
'setAccessibilityMode'
'toggleVisibleEditor'
],
ns
);

View File

@ -31,7 +31,6 @@ const initialState = {
challengeTests: [],
consoleOut: [],
hasCompletedBlock: false,
inAccessibilityMode: false,
isCodeLocked: false,
isBuildEnabled: true,
logsOut: [],
@ -131,9 +130,6 @@ export const setEditorFocusability = createAction(
export const toggleVisibleEditor = createAction(
actionTypes.toggleVisibleEditor
);
export const setAccessibilityMode = createAction(
actionTypes.setAccessibilityMode
);
export const currentTabSelector = state => state[ns].currentTab;
export const challengeFilesSelector = state => state[ns].challengeFiles;
@ -211,9 +207,6 @@ export const challengeDataSelector = state => {
export const canFocusEditorSelector = state => state[ns].canFocusEditor;
export const visibleEditorsSelector = state => state[ns].visibleEditors;
export const inAccessibilityModeSelector = state =>
state[ns].inAccessibilityMode;
export const reducer = handleActions(
{
[actionTypes.createFiles]: (state, { payload }) => ({
@ -361,11 +354,7 @@ export const reducer = handleActions(
[payload]: !state.visibleEditors[payload]
}
};
},
[actionTypes.setAccessibilityMode]: (state, { payload }) => ({
...state,
inAccessibilityMode: payload
})
}
},
initialState
);