#41872 closed defect (bug) (fixed)
Code Editor: Minor accessibility improvements to the CodeMirror editing areas
Reported by: | afercia | Owned by: | afercia |
---|---|---|---|
Milestone: | 4.9 | Priority: | high |
Severity: | normal | Version: | 4.9 |
Component: | Customize | Keywords: | has-patch has-screenshots commit |
Focuses: | ui, accessibility, administration | Cc: |
Description
The CodeMirror-powered code editor areas recently introduced in [41376] can be improved a bit with some minor accessibility enhancements.
First of all, the CodeMirror editing area needs a proper ARIA role and aria-multiline
attribute to be exposed to assistive technologies as equivalent to a native HTML textarea. This was mentioned in the original ticket, see https://core.trac.wordpress.org/ticket/12423#comment:49
Further improvements:
- all the editing areas need to be labeled, whether using a
<label>
element, anaria-label
, or anaria-labelledby
attribute. - all the underlying textarea elements need to be labeled, this is particularly important when CodeMirror is disabled in the user profile and the textarea are actually used
- worth noting the Custom HTML widget used to have a "Content:" label that was removed, it should be restored also for consistency with all the other widgets
- the Additional CSS textarea in the Customizer needs a label
- the Plugin and Theme editors miss a label since forever (I guess), this is a good opportunity to add it
- the help text with instructions to escape from the keyboard trap related to the Tab key needs to be consistently used as target for
aria-describedby
on both the textarea elements and the CodeMirror editing areas - this is a nice opportunity to improve the help text and make it consistent, users and translators will be happy
- the Additional CSS help toggle and panel
aria-expanded
attribute needs to be fixed, see https://github.com/WordPress/better-code-editing/issues/89
Attachments (6)
Change History (31)
#3
@
7 years ago
- Owner set to melchoyce
- Status changed from new to assigned
@afercia the code changes look good, other than the jQuery for obtaining .CodeMirror-code
. This can be simplified by just accessing editor.codemirror.display.lineDiv
. Done in 41872.2.diff.
Otherwise, for the text changes and label additions, I'll defer to @melchoyce, @michelleweber, and @mizejewski.
#5
@
7 years ago
and label additions
Worth noting the label for the Custom HTML widget is not an addition :) actually, in 4.8 there's a label and it was removed in the CodeMirror patch, which is an a11y regression.
#7
@
7 years ago
An additional change needed for 41872.2.diff. When clicking on the label it should focus on the CodeMirror editor.
In other words:
$( label ).on( 'click', function() { editor.codemirror.focus(); } );
#8
@
7 years ago
Yeah, I was hesitant to address also the focus issue, because, ideally, that should work out of the box :( I've also quickly tried that and it triggers some weird behaviors:
- in Firefox, the page scrolls and the editor area first line goes under the WP toolbar
- in both Chrome and Firefox, if one line in the editor area was previously focused, clicking the label puts focus on that line because I guess CodeMirror remembers the previous insertion point; this behaviour is confusing when the focused line is outside of the visible editor area portion (which doesn't scroll)
About the Help text, see also the discussion on Slack.
#9
@
7 years ago
Trying to keep the Help text as an unordered list and at the same time using this text as target for aria-describedby
is not so easy because the text is composed by separate strings (and elements):
There are basically two options:
- wrap the whole Help text within a container with an ID and target the wrapper using
aria-describedby="wrapper-ID"
: this doesn't work consistently across various browsers/screen readers combinations, see test results below aria-describedby
accepts multiple IDs so can target multiple elements; this would require to use a unique ID on each element of the Help text and target them this way:aria-describedby="element-1 element-2 element-3 element-4"
; this works with all combos I've tested with, but it's not so clean in terms of code, especially for the JavaScript part
However, there's one more important concern: translations. Ideally, messages that are meaningful as a whole, shouldn't be split in separate strings. Splitting a string, increases the chances the whole message will be translated inconsistently and should be avoided. Feedback from the polyglots team would be very appreciated.
Test results: for the ones who want to have some fun testing with screen readers, I've prepared 3 codepens:
Test aria-describedby targeting parent element with multiple children
https://codepen.io/afercia/full/XeJxwB
Test aria-describedby targeting parent element (hidden with display none) with multiple children
https://codepen.io/afercia/full/YrPdmj/
Test aria-describedby targeting multiple elements
https://codepen.io/afercia/full/BwyGNp
Safari + VoiceOver have a very weird behavior, where also the visibility of the help text plays a role. When targeting the wrapper, the whole text gets announced only if it's hidden with display: none
. Instead, when it's visible, only the first sentence gets read out. For clarity, I've made a short video:
https://cloudup.com/cCcpmOxRjqi
Conclusion: I'd recommend to keep it simple and use just a single element (a paragraph). Worth also noting the Help text should be the same in 4 different places, and when used in the admin pages Help tabs, a list might not look so nice: depending on the screen width and translations, there's the chance the text will wrap producing a few "widows", for example:
#10
@
7 years ago
- Summary changed from Minor accessibility improvements to the CodeMirror editing areas to Code Editor: Minor accessibility improvements to the CodeMirror editing areas
#11
@
7 years ago
- Priority changed from normal to high
Bumping priority to high for visibility and alignment with 4.9 goals, and given proximity to beta 1 deadline.
#12
@
7 years ago
Conclusion: I'd recommend to keep it simple and use just a single element (a paragraph).
I still think it'll be much easier for sighted users to understand if it's broken up into paragraphs and list items. If we decide to do one paragraph, then I think we need to revisit the decision to open these instructions by default. I don't want to overwhelm people with a giant paragraph the first time they open the CSS panel.
Is there a way to add a note for translators to look at all the strings in context before translating?
Worth also noting the Help text should be the same in 4 different places, and when used in the admin pages Help tabs, a list might not look so nice: depending on the screen width and translations, there's the chance the text will wrap producing a few "widows", for example.
That's fine — nothing can be expected to be perfect when you're dealing with variable widths. :)
#13
@
7 years ago
- Keywords needs-refresh added
I've worked a bit in the last days to a patch to keep the list in all the 4 places where the help text is used. Just need to refresh it after some recent changes to core.
Worth noting that, to keep the list and also target the proper elements with aria-describedby, there's the need to do things like this for the HTML part:
aria-describedby="editor-keyboard-trap-help-1 editor-keyboard-trap-help-2 editor-keyboard-trap-help-3 editor-keyboard-trap-help-4"
and this for the JS part:
'aria-describedby' => 'editor-keyboard-trap-help-1 editor-keyboard-trap-help-2 editor-keyboard-trap-help-3 editor-keyboard-trap-help-4'
which is ugly 😞
@westonruter thoughts?
I'll upload the patch as soon as I have time to refresh it.
#14
follow-up:
↓ 15
@
7 years ago
- Owner changed from melchoyce to afercia
@afercia Thank you for working on that tedious task. The beauty of the code is always secondary to the benefit the code will yield to the users (in both visual and aural modes), so if this compound aria-describedby
is what it takes then I fully support it. Besides, it's not so ugly so much as it is verbose. 👍
#15
in reply to:
↑ 14
@
7 years ago
Replying to westonruter:
@afercia Thank you for working on that tedious task. The beauty of the code is always secondary to the benefit the code will yield to the users (in both visual and aural modes), so if this compound
aria-describedby
is what it takes then I fully support it. Besides, it's not so ugly so much as it is verbose. 👍
+1!
#16
follow-up:
↓ 19
@
7 years ago
When clicking on the label it should focus on the CodeMirror editor.
Trying this on the Additional CSS, focus always goes to the last line (and if the content is very long, it's out of view). Seems to me because of:
// Refresh when receiving focus. control.editor.codemirror.on( 'focus', function( codemirror ) { codemirror.refresh(); });
Is this really necessary? And why it is used only for the Additional CSS and not for the other CodeMirror instances? If there are no particular reasons, I'd consider to remove it.
This ticket was mentioned in Slack in #core-customize by afercia. View the logs.
7 years ago
#18
@
7 years ago
- Keywords needs-refresh removed
41872.3.diff tries to refactor the patch to keep the help text with the unordered list. Things to check:
- please check how
input_attrs
is passed to the JS template - added a third item to the "keyboard trap" help text list and reviewed the pre-existing text to make it a bit shorter and more clear; feedback for better wording/English welcome
- the "keyboard trap" help text is now the same in all the 4 places where it is used; maybe it could use a function to avoid repetition. Not sure where the function should go to be available both in the admin screens and in the Customizer
- Custom HTML widget: some help text should be displayed only when CodeMirror is enabled, made some changes accordingly
- Additional CSS: focus issue when clicking on the label, see comment above
- removed the URL fragment identifier used for the link to the profile page
profile.php#syntax_highlighting
because in the profile page the related control stays hidden behind the admin toolbar (see screenshot below) - does
get_edit_profile_url()
needs to be escaped? seeesc_url( get_edit_profile_url() )
About translations: the "keyboard trap" help text is now composed by 4 strings. As mentioned before, not sure this is so ideal for translation and I'd like to have some feedback. /cc @ocean90 @SergeyBiryukov
Screenshot of the profile page with the Syntax Highlighting
control hidden by the admin bar:
Screenshot of the keyboard trap help text in the Customizer > Additional CSS:
(the same text is used in the plugin/theme editors and targeted by aria-describedby for the Custom HTML widget)
#19
in reply to:
↑ 16
@
7 years ago
Replying to afercia:
When clicking on the label it should focus on the CodeMirror editor.
Trying this on the Additional CSS, focus always goes to the last line (and if the content is very long, it's out of view). Seems to me because of:
// Refresh when receiving focus. control.editor.codemirror.on( 'focus', function( codemirror ) { codemirror.refresh(); });Is this really necessary? And why it is used only for the Additional CSS and not for the other CodeMirror instances? If there are no particular reasons, I'd consider to remove it.
Oh thank you for identifying this!! I had opened #41900 for this issue. I'll follow up there with working to remove this.
#21
@
7 years ago
- Keywords commit added
@afercia looks good! I made just a couple tweaks for alignment with coding standards. Go ahead and commit.
#22
@
7 years ago
@afercia 41872.5.diff ensures that all of the input_attrs
are output by looping over each one. This is what will be required by #30738.
#23
@
7 years ago
41872.6.diff refreshed after recent changes. Also: consistently escapes $scrollto
and removes a few default
textdomains.
41872.diff is a first pass to try to address the points above.
Also:
type="button"
attribute, so there's no need to prevent the default action, use a keydown event, and filter the keys. They just need a click event<big>
element to<h2>
for consistency with the Theme editor pagearia-describedby
About the new Help text, I'd say it's important that is always the same everywhere to avoid confusion for users and make translators happy. New text:
@westonruter I'd greatly appreciate your feedback and review.