Problem/Motivation
In ajax dialogs, there is a accessibility issue with invisible duplicate buttons.
When the dialog is created, the buttons are created in the dialog footer, which cause the original buttons to fire programatically. The original buttons are hidden using a zero-width technique, but they are still operable. This causes problems for some users:
- Sighted keyboard are the most severely affected group.
- Users will encounter some extra tab stops, without knowing what they are focused on.
- This is a WCAG level AA failure of success criterion 2.4.7"Focus Visible".
- It's disorienting, and can cause users to over- or under-shoot when pressing TAB repeatedly.
- Worse, an undershoot when tabbing, can make it easy to accidentally activate the wrong button.
- Screen reader users are informed of both sets. Both sets work, so it's harmless but confusing.
- Speech control users may encounter them if using a "show numbers" tool. They won't know what the buttons do, but so long as they do not speak the number, they can avoid accidentally activating the wrong button.
For some arcane reason we can't hide the originals with display:none
otherwise it won't work. See this comment in prepareDialogButtons()
, dialog.ajax.es6.js
:
// Hidden form buttons need special attention. For browser consistency,
// the button needs to be "visible" in order to have the enter key fire
// the form submit event. So instead of a simple "hide" or
// "display: none", we set its dimensions to zero.
// See http://mattsnider.com/how-forms-submit-when-pressing-enter/
The linked article says this is about some legacy browsers from back in the days of IE8.
Proposed resolution
Investigate: is the workaround still necessary? We dropped support for IE8 ages ago.
Ideally, we'd like to use display: none
to hide these buttons from everyone.
If it is still necessary, we can try adding tabindex="-1" aria-hidden="true"
to them. It would work, but it's a bit hacky.
Remaining tasks
Patch.
Warrants cross-browser testing whatever approach we use.
User interface changes
TODO. Improve the
API changes
TODO
Data model changes
None.
Comment | File | Size | Author |
---|---|---|---|
#15 | 3037781-15.patch | 3.47 KB | bnjmnm |
#15 | interdiff_9-15.txt | 3.9 KB | bnjmnm |
#9 | 3037781-9.patch | 3.36 KB | bnjmnm |
#9 | interdiff_6-9.txt | 2.81 KB | bnjmnm |
#9 | 3037781-9-TEST-ONLY-WILL-FAIL.patch | 1.86 KB | bnjmnm |
Comments
Comment #2
andrewmacpherson CreditAttribution: andrewmacpherson as a volunteer and at Annertech commentedfinishing my unfinished sentence in issue summary
Comment #4
rainbreaw CreditAttribution: rainbreaw as a volunteer and commentedThis is related to the issue found and resolved here:
#3078966 Remove hidden tabbable focus area from editor dialogs
Comment #5
andrewmacpherson CreditAttribution: andrewmacpherson as a volunteer and at Annertech commentedThis issue is about all of our dialogs. The other one is specifically trying to fix something in the editor dialog. Maybe it can be closed as a duplicate of this one?
Turns out there are several different JS libraries that create dialogs. We have dialog.js, dialog.ajax.js, and some others which are specific to particular modules.
I think
display:none
will be preferable as the simplest way to remove these buttons for everyone, instead of layering visually-hidden, tabindex -1, and aria-hidden as separate solutions for different user groups.Comment #6
bnjmnmI've been running into this all day while testing screenreader functionality in Media Library, figured there must already be an issue, and it probably had something to do with
prepareDialogButtons()
in dialog.ajax.es6.js, as that is what moves submit buttons from the output of the form controller to the dialog buttonpaneI went in intending to go with the
display: none
approach suggested in #5, then saw this commentBased on this, I went with tabindex. This fixes the issue for me, and also fixes the symptoms reported in #3078966: Remove hidden tabbable focus area from editor dialogs tagging with Needs manual testing due to witnessing many past attempts at adding tab navigation to Javascript tests that did not pan out.
Comment #7
seanBI think this was a test thingy that needs to be removed?
Besides that we could use a test to verify the attribute is set correctly.
Comment #8
bnjmnmMy "console.log the dumbest thing possible so I remember to get rid of it" approach apparently didn't pay off. Good call on a test to check for the attribute. This is something that should receive test coverage even if simulating tab navigation is not feasible.
Comment #9
bnjmnmAdded tests and cleaned up the JS.
Comment #11
seanBNice job, it works as expected. Very important improvement if you ask me.
I think this needs a11y maintainer sign-off, but the code looks great!
Comment #12
Wim LeersGiven how many AJAX dialogs Drupal core has, bumping to
priority.Comment #13
andrewmacpherson CreditAttribution: andrewmacpherson as a volunteer and at Annertech commentedPatch #9 doesn't fully implement either of the suggestions in the proposed resolution.
It only adds a
tabindex="-1"
on the original (visually hidden) button. That removes it from the tabbing order, but isn't sufficient to hide it from assistive technology. It needsaria-hidden="true"
as well.Is the zero dimension hack still needed? The article explaining it says it is a workaround for IE8, which we no longer support. If it's no longer needed for IE11, then using
display:none;
will be all that is needed (instead of combining dimensions, tabindex, and aria-hidden).Comment #14
Wim LeersVery good point, @andrewmacpherson, here's hoping to removing one IE hack! 😁
Comment #15
bnjmnmVERY good call in #13, the superior
display:none
is now the approach.Tested this in IE11 and all current OSX browsers and submitting via return key works properly, so the width/height 0 approach doesn't appear to be necessary anymore.
Comment #16
Wim Leers@bnjmnm did manual testing to verify what @andrewmacpherson wrote. Test coverage has been updated. Code is now simpler. With less code, we now have better accessibility. Wonderful :)
Comment #18
webchickGreat work, everyone!! Loving the focus (ba-dum-pssh) on accessibility with the Media Library!
Committed and pushed to 8.8.x. Thanks!
Comment #20
idebr CreditAttribution: idebr at iO commentedThis issue also fixed a visual artefact in Claro since the button is now actually removed from the accessibility tree: #3053684: .button {border: 1px solid transparent !important;} causes blue pixel artefact in modal content