KittyGiraudel / a11y-dialog

A very lightweight and flexible accessible modal dialog script.
https://a11y-dialog.netlify.app
MIT License
2.42k stars 130 forks source link

Feature request: Option to disable Focus Restoration #629

Closed raicubogdan closed 3 months ago

raicubogdan commented 10 months ago

Hello,

We've run into an issue with the way we're using the A11yDialog and the feature of Focus Restoration as described in the documentation here: https://a11y-dialog.netlify.app/advanced/focus-considerations#focus-restoration

Our feature: we have a scrollable list of cards and each card opens an A11yDialog on click/enter press. The dialog does not cover the entirety of the page, but is a sibling of the list of cards I've just mentioned. The dialog has position: sticky as a css rule, keeping it in view while the list scrolls.

Focus Restoration works as intended when the user navigates with the keyboard, as the focus is trapped inside the dialog, making it impossible for the user to further scroll the list of cards.

It is when the user clicks a card that problems start to arise: let's say we have many results in the list and we enter an overflow scenario. The user navigates with the mouse and clicks a card, thus opening a dialog. The user then proceeds to further scroll down the list and clicks another card. What happens then is that focus moves back to the previously focused element (the card that opened the dialog), thus making the user experience an unexpected jump in the cards list. Or, if the user closes the dialog and they have already moved away from the previously focused element while navigating with the mouse, the same jump occurs. It is especially visible if smooth scrolling is applied to the whole document.

The solution we came up with: if the user opens a dialog with click (uses mouse navigation), we set _previouslyFocused to null on the current instance after the show() event has been triggered. We also locked our version at 7.5.2 to make sure no changes interfere with the current behaviour.

The request: It would be helpful and less hack-ish for us if A11yDialog would have a way to disable Focus Restoration.

Thank you for your time, attention and this useful component!

KittyGiraudel commented 7 months ago

Hello Bogdan!

Thank you for opening an issue and my apologies for leaving it unanswered for so long. It’s quite a nifty case you have here. Have you tried using the data-a11y-dialog-ignore-focus-trap attribute as mentioned in the documentation, in order to circumvent the focus restoration? You may have to patch the focus behavior yourself, but it seems like it should be doable?

jlango791 commented 5 months ago

Hello @KittyGiraudel ,

We would also like a way to skip the focus restoration on dialog dismiss.

We have one set of dialogs that are triggered by a focused input box (not the best idea, I know), and when they are dismissed, the focus restoration triggers them to open again.

As a workround, we've created another data attribute for the dialog container, and in hide() we skip the focus call if it is found. Basically this:


if (!this.$el.hasAttribute('data-a11y-dialog-skip-focus-return')) {
    this.previouslyFocused?.focus();
}
KittyGiraudel commented 4 months ago

Generally speaking, I am a little weary of adding an explicit way to opt-out from the focus restoration — it’s such an important part of building an accessible dialog, and one of the key points of a11y-dialog. There are very few cases where it should be needed (and as you said, most of them are not a good idea), so I’m hesitant in adding more code for that.

I tend to think that the data-a11y-dialog-ignore-focus-trap escape hatch and some custom JS logic is enough for these weird cases, but maybe I’m wrong of course.