ember-modal-dialog
ember-modal-dialog copied to clipboard
Accessibility: Keyboard Navigation Support
Thank you for this addon! I noticed some missing keyboard navigation support, which would be required to meet ADA compliance criteria- plus it's super helpful for any type of user!
- Pressing the ESC key should close the modal
- When the modal is open, focus should stay inside the open modal window (right now it is not getting trapped inside of the open modal window).
- Pressing the TAB key should take the visual focus to the next interactive element inside of the modal. If the user is at the last interactive element, pressing TAB again should take them to the first interactive element inside of the modal.
- SHIFT+TAB should also stay inside the modal. When the first interactive element is reached, pressing SHIFT + TAB again should return the user to the last interactive element inside of the modal.
Thanks, @MelSumner! The README describes how to add support for the ESC key: https://github.com/yapplabs/ember-modal-dialog#keyboard-shortcuts. I'd welcome an addition by you or another contributor describing how to implement capturing focus -- what are the recommended approaches for this?
I’d like to hear more about this too, as the only techniques I can find seem quite messy, like setting all non-modal elements to tabindex=-1 and then setting it back after the modal has been removed. If that’s permissible, I’d be into working on PR to do so.
I also found this CSS technique which is also seems scandalous but maybe less so? 🤔
I think it's worth noting that the ember-keyboard solution is not always as simple as the readme suggests. (e.g. see https://github.com/patience-tema-baron/ember-keyboard/issues/56) The problem I'm having is probably because of something dumb that I did in my app without knowing it (or perhaps in MaterializeCSS, which I'm using), but I can run monitorEvents(document.body, "keydown"); and see events firing, yet the modal's handler doesn't seem to get called unless I tab to a button (outside the modal, but that's a separate problem) and then press the key. If that wasn't weird enough, it works from that point on (i.e. if I re-open the modal I can close it by pressing escape).
import { on } from '@ember/object/evented';
import ModalDialog from 'ember-modal-dialog/components/modal-dialog';
import { EKMixin, EKOnInsertMixin, keyDown } from 'ember-keyboard';
import * as debug from 'debug';
const log = debug('my-app:my-modal');
export default ModalDialog.extend(EKMixin, EKOnInsertMixin, {
// Doesn't fire (without messing around)
closeOnEsc: on(keyDown('Escape'), function () {
log('Pressed Esc (keyDown)');
const f = this.get('onClose');
if (typeof f === 'function')
f();
})
});
Edit: To be clear, I'm not saying that this is the fault of ember-modal-dialog or even ember-keyboard. I haven't even nailed down what's causing my bug. It just surprised me that I was able to accidentally make a weird / intermittent bug (I thought it was more fool-proof / robust).
Coming back around to this (sorry it took me so long)- there are a few ways that focus trapping could be achieved:
- ember addons that provide focus trapping
- use of inert (currently available as a browser polyfill)
- tracking the what's inside the modal, and what's not, and applying aria-hidden and negative tabindex to it
While YMMV, here is a simple and accessible modal addon that could be evaluated for it's potential: https://github.com/melsumner/e-a11y-modal (there's a deployed link in the github repo as well, so you could try it out and see what it does)
I've also done a bit of research, and documented it here: https://github.com/MelSumner/ember-a11y-roadmap/blob/master/rfc-research/dialogs/modals.md
Please let me know if there's any other way I can help.