feat: add accessibility toggle
Users can now press ctrl/cmd+f1 to toggle the screen reader mode, in addition to using the accessibility tooltip. The mode now persists between challenges. If screen reader mode is on, the instructions are focused by default so the user is not required to navigate to them before reading starts.
This commit is contained in:
committed by
mrugesh
parent
265e383705
commit
c5d4bedda5
@ -6,7 +6,9 @@ import { createSelector } from 'reselect';
|
||||
import {
|
||||
canFocusEditorSelector,
|
||||
executeChallenge,
|
||||
inAccessibilityModeSelector,
|
||||
setEditorFocusability,
|
||||
setAccessibilityMode,
|
||||
updateFile
|
||||
} from '../redux';
|
||||
import { userSelector, isDonationModalOpenSelector } from '../../../redux';
|
||||
@ -22,6 +24,8 @@ const propTypes = {
|
||||
executeChallenge: PropTypes.func.isRequired,
|
||||
ext: PropTypes.string,
|
||||
fileKey: PropTypes.string,
|
||||
inAccessibilityMode: PropTypes.bool.isRequired,
|
||||
setAccessibilityMode: PropTypes.func.isRequired,
|
||||
setEditorFocusability: PropTypes.func,
|
||||
theme: PropTypes.string,
|
||||
updateFile: PropTypes.func.isRequired
|
||||
@ -29,16 +33,19 @@ const propTypes = {
|
||||
|
||||
const mapStateToProps = createSelector(
|
||||
canFocusEditorSelector,
|
||||
inAccessibilityModeSelector,
|
||||
isDonationModalOpenSelector,
|
||||
userSelector,
|
||||
(canFocus, open, { theme = 'default' }) => ({
|
||||
(canFocus, accessibilityMode, open, { theme = 'default' }) => ({
|
||||
canFocus: open ? false : canFocus,
|
||||
inAccessibilityMode: accessibilityMode,
|
||||
theme
|
||||
})
|
||||
);
|
||||
|
||||
const mapDispatchToProps = {
|
||||
setEditorFocusability,
|
||||
setAccessibilityMode,
|
||||
executeChallenge,
|
||||
updateFile
|
||||
};
|
||||
@ -114,7 +121,12 @@ class Editor extends Component {
|
||||
|
||||
editorDidMount = (editor, monaco) => {
|
||||
this._editor = editor;
|
||||
if (this.props.canFocus) {
|
||||
this._editor.updateOptions({
|
||||
accessibilitySupport: this.props.inAccessibilityMode ? '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 (this.props.canFocus && !this.props.inAccessibilityMode) {
|
||||
this._editor.focus();
|
||||
} else this.focusOnHotkeys();
|
||||
this._editor.addAction({
|
||||
@ -135,9 +147,33 @@ class Editor extends Component {
|
||||
this.props.setEditorFocusability(false);
|
||||
}
|
||||
});
|
||||
this._editor.addAction({
|
||||
id: 'toggle-accessibility',
|
||||
label: 'Toggle Accessibility Mode',
|
||||
keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.F1],
|
||||
run: () => {
|
||||
const currentAccessibility = this.props.inAccessibilityMode;
|
||||
// The store needs to be updated first, as onDidChangeConfiguration is
|
||||
// called before updateOptions returns
|
||||
this.props.setAccessibilityMode(!currentAccessibility);
|
||||
this._editor.updateOptions({
|
||||
accessibilitySupport: currentAccessibility ? 'auto' : 'on'
|
||||
});
|
||||
}
|
||||
});
|
||||
this._editor.onDidFocusEditorWidget(() =>
|
||||
this.props.setEditorFocusability(true)
|
||||
);
|
||||
// This is to persist changes caused by the accessibility tooltip.
|
||||
// Unfortunately it relies on Monaco's implementation details
|
||||
this._editor.onDidChangeConfiguration(() => {
|
||||
if (
|
||||
this._editor.getConfiguration().accessibilitySupport === 2 &&
|
||||
!this.props.inAccessibilityMode
|
||||
) {
|
||||
this.props.setAccessibilityMode(true);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
focusOnHotkeys() {
|
||||
|
@ -29,6 +29,7 @@ const initialState = {
|
||||
},
|
||||
challengeTests: [],
|
||||
consoleOut: '',
|
||||
inAccessibilityMode: false,
|
||||
isCodeLocked: false,
|
||||
isBuildEnabled: true,
|
||||
modal: {
|
||||
@ -78,7 +79,8 @@ export const types = createTypes(
|
||||
|
||||
'moveToTab',
|
||||
|
||||
'setEditorFocusability'
|
||||
'setEditorFocusability',
|
||||
'setAccessibilityMode'
|
||||
],
|
||||
ns
|
||||
);
|
||||
@ -152,6 +154,7 @@ export const submitChallenge = createAction(types.submitChallenge);
|
||||
export const moveToTab = createAction(types.moveToTab);
|
||||
|
||||
export const setEditorFocusability = createAction(types.setEditorFocusability);
|
||||
export const setAccessibilityMode = createAction(types.setAccessibilityMode);
|
||||
|
||||
export const currentTabSelector = state => state[ns].currentTab;
|
||||
export const challengeFilesSelector = state => state[ns].challengeFiles;
|
||||
@ -223,6 +226,8 @@ export const challengeDataSelector = state => {
|
||||
};
|
||||
|
||||
export const canFocusEditorSelector = state => state[ns].canFocusEditor;
|
||||
export const inAccessibilityModeSelector = state =>
|
||||
state[ns].inAccessibilityMode;
|
||||
|
||||
const MAX_LOGS_SIZE = 64 * 1024;
|
||||
|
||||
@ -359,6 +364,10 @@ export const reducer = handleActions(
|
||||
[types.setEditorFocusability]: (state, { payload }) => ({
|
||||
...state,
|
||||
canFocusEditor: payload
|
||||
}),
|
||||
[types.setAccessibilityMode]: (state, { payload }) => ({
|
||||
...state,
|
||||
inAccessibilityMode: payload
|
||||
})
|
||||
},
|
||||
initialState
|
||||
|
Reference in New Issue
Block a user