fix(a11y): add editor name to editor aria-label (#60529)

This commit is contained in:
Huyen Nguyen
2025-06-23 20:53:33 +07:00
committed by GitHub
parent cb231abaaa
commit 723be55e62
3 changed files with 35 additions and 12 deletions

View File

@@ -858,6 +858,10 @@
"rsa-checkbox": "I have tried the Read-Search-Ask method", "rsa-checkbox": "I have tried the Read-Search-Ask method",
"similar-questions-checkbox": "I have searched for similar questions that have already been answered on the forum", "similar-questions-checkbox": "I have searched for similar questions that have already been answered on the forum",
"edit-my-profile": "Edit my profile", "edit-my-profile": "Edit my profile",
"editor-a11y-off-macos": "{{editorName}} editor content. Press Option+F1 for accessibility options.",
"editor-a11y-off-non-macos": "{{editorName}} editor content. Press Alt+F1 for accessibility options.",
"editor-a11y-on-macos": "{{editorName}} editor content. Accessibility mode set to 'on'. Press Command+E to disable or press Option+F1 for more options.",
"editor-a11y-on-non-macos": "{{editorName}} editor content. Accessibility mode set to 'on'. Press Ctrl+E to disable or press Alt+F1 for more options.",
"terminal-output": "Terminal output" "terminal-output": "Terminal output"
}, },
"flash": { "flash": {

View File

@@ -239,7 +239,14 @@ const initialData: EditorProperties = {
const Editor = (props: EditorProps): JSX.Element => { const Editor = (props: EditorProps): JSX.Element => {
const { t } = useTranslation(); const { t } = useTranslation();
const { editorRef, initTests, resetAttempts, isMobileLayout } = props; const {
editorRef,
initTests,
resetAttempts,
isMobileLayout,
challengeFiles,
fileKey
} = props;
// These refs are used during initialisation of the editor as well as by // These refs are used during initialisation of the editor as well as by
// callbacks. Since they have to be initialised before editorWillMount and // callbacks. Since they have to be initialised before editorWillMount and
// editorDidMount are called, we cannot use useState. Reason being that will // editorDidMount are called, we cannot use useState. Reason being that will
@@ -275,6 +282,12 @@ const Editor = (props: EditorProps): JSX.Element => {
const attemptsRef = useRef<number>(0); const attemptsRef = useRef<number>(0);
attemptsRef.current = props.attempts; attemptsRef.current = props.attempts;
const challengeFile = challengeFiles?.find(
challengeFile => challengeFile.fileKey === fileKey
);
const ariaEditorName = `${challengeFile?.name}.${challengeFile?.ext}`;
const options: editor.IStandaloneEditorConstructionOptions = { const options: editor.IStandaloneEditorConstructionOptions = {
fontSize: 18, fontSize: 18,
fontFamily: 'Hack-ZeroSlash, monospace', fontFamily: 'Hack-ZeroSlash, monospace',
@@ -335,7 +348,7 @@ const Editor = (props: EditorProps): JSX.Element => {
}; };
const editorWillMount = (monaco: typeof monacoEditor) => { const editorWillMount = (monaco: typeof monacoEditor) => {
const { challengeFiles, fileKey, usesMultifileEditor } = props; const { usesMultifileEditor } = props;
monacoRef.current = monaco; monacoRef.current = monaco;
defineMonacoThemes(monaco, { usesMultifileEditor }); defineMonacoThemes(monaco, { usesMultifileEditor });
@@ -344,9 +357,6 @@ const Editor = (props: EditorProps): JSX.Element => {
// swap and reuse models, we have to create our own models to prevent // swap and reuse models, we have to create our own models to prevent
// disposal. // disposal.
const challengeFile = challengeFiles?.find(
challengeFile => challengeFile.fileKey === fileKey
);
const model = const model =
dataRef.current.model || dataRef.current.model ||
monaco.editor.createModel( monaco.editor.createModel(
@@ -414,15 +424,26 @@ const Editor = (props: EditorProps): JSX.Element => {
const storedAccessibilityMode = () => { const storedAccessibilityMode = () => {
const accessibility = store.get('accessibilityMode') as boolean; const accessibility = store.get('accessibilityMode') as boolean;
const isMacOS = navigator.userAgent.includes('Mac OS');
const a11yOffText = isMacOS
? t('aria.editor-a11y-off-macos', { editorName: ariaEditorName })
: t('aria.editor-a11y-off-non-macos', { editorName: ariaEditorName });
const a11yOnText = isMacOS
? t('aria.editor-a11y-on-macos', { editorName: ariaEditorName })
: t('aria.editor-a11y-on-non-macos', { editorName: ariaEditorName });
if (!accessibility) { if (!accessibility) {
store.set('accessibilityMode', false); store.set('accessibilityMode', false);
editor.updateOptions({
ariaLabel: a11yOffText
});
} }
// 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) { if (accessibility) {
editor.updateOptions({ editor.updateOptions({
ariaLabel: ariaLabel: a11yOnText
'Accessibility mode set to true. Press Ctrl+e to disable or press Alt+F1 for more options'
}); });
} }

View File

@@ -1,9 +1,7 @@
import { type Page } from '@playwright/test'; import { type Page } from '@playwright/test';
export const getEditors = (page: Page) => { export const getEditors = (page: Page) => {
return page.getByLabel( return page.getByRole('textbox', { name: /editor content/i });
'Editor content;Press Alt+F1 for Accessibility Options'
);
}; };
export const focusEditor = async ({ export const focusEditor = async ({