morkro / vue-a11y-dialog

Vue.js component for a11y-dialog

Home Page:https://www.npmjs.com/package/vue-a11y-dialog

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

API documentation: app-root="#app" may not be the best example

marcus-herrmann opened this issue · comments

In the project's readme, there is a example of the app-root prop and an explanation of what it does:

<a11y-dialog app-root="#app">
  <!-- ... -->
</a11y-dialog>
Description: The selector(s) a11y-dialog needs to disable when the dialog is open.

The problem is that, once you apply aria-hidden=true to <div id="app" />, everything inside it will be removed from the accessibility tree, including the modal itself. You can see this behaviour in your official demo: https://rj20wr1kpp.codesandbox.io/

As WAI ARIA Authoring Practices, Modal Dialogs, state (see green note box, lower part):

aria-hidden is set to true on each element containing a portion of the inert layer. ... The dialog element is not a descendant of any element that has aria-hidden set to true.

Therefore, at least the readme should be changed. If possible you should rename app-root to its actual function, maybe render-inert.

I wrote a blog post on how to use your component differently (circa last third of the article): https://marcus.io/blog/a11y-app-dialogs-modals

But nevertheless, thanks for your handy wrapper of a11y-dialog!

Hey there.

I can’t speak for vue-a11y-dialog, but the way it works on react-a11y-dialog is that it renders the dialogs in a separate container from the app root through a React portal. Therefore these containers’ aria-hidden can safely be toggled: one is hidden, not the other.

<Dialog appRoot='#app-root' dialogRoot='#dialog-root' {...otherConfigProps} />
<div id="app-root" />
<div id="dialog-root" />

"#app" is in Vue's documentation and examples very often the overall wrapping container, so even when you are using PortalVue (see my blog post above) the following open modal would render the whole app inert:

<div id="app">
    <div id="wrapper">
          <portal to="modals">
                <a11y-dialog app-root="#app">
                <!-- ... -->
                </a11y-dialog>
         </portal>
    </div>
    <portal-target name="modals"></portal-target>
</div>

@hugogiraudel Thanks for the explanation! 🎉

I think we can still achieve the same effect with PortalVue, there is some documentation for rendering a portal outside of a Vue application. I'll do some prototyping with it and see if that works :)

Just some updates here. I did some prototyping and generally this seems to work. However, the API (targetEl) to render a portal outside of a Vue application comes with its own issues making this as of now not ready to be implemented without major workarounds.

The library author is aware of these issues and plans to rework the API with the next release for PortalVue. I don't know when that is scheduled though.

I will follow the development of PortalVue and consider releasing a new version of vue-a11y-dialog with some workarounds to at least address the accessibility issues.

I've just published a fix for this :)