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

issue rendering two dialogs on the same page.

renatodeleao opened this issue · comments

Thanks for the wrapper, i'm fan of the original plugin, and will be of this wrapper for sure :)

This sounds like a dumb question (and probably is), but i want to render [2..n] dialogs in one page. For demo purposes i went with 2, and currently it's only rendering the last one. For the first i'm getting the following error for the first :

DOMException: Failed to execute 'showModal' on 'HTMLDialogElement': The element is not in a Document.

Demo link

My suspicions go to the portal-target. Since we're using the "html" version of it i suspect we don't get the multiple option that comes with the component version <portal-target multiple>, but i might be wrong, so I wanted to get your input on this.

Thanks for your time! ✋

Hey @renatodeleao! Thanks for pointing this out, I am aware of that issue as well. I believe this is fixed with an upcoming version of PortalVue and I am kinda waiting for that update to be honest. If this issue isn't resolved any time soon, I will have to either put a warning in the README or suggest solutions.

In one of my projects, I've overcome this problem (here and here) by wrapping vue-a11y-dialog in another component which uses again <portal>s to place content. By that I am able to use multiple dialogs in one screen, while technically only using one dialog. I am happy to elaborate on my solution if that helps :)

that's a clever trick, thanks for sharing!
I've saw the issue on PortalVue, i'll keep an eye on it as well!

Cheers!

But i'm curious, is there a particular reason why you've chosen :target-el over :to prop?

<portal :target-el="portalTarget">

Both are dynamic and could be opt-in. Pseudo-code:

<portal v-bind="destination" >
....

props: ['renderMode'],
computed: {
  destination() {
    return this.renderMode === "outside" 
       ? {"target-el": this.portalTarget }
       :  {"to" :  this.portalTarget }
  }
}

target-el is the API referenced for rendering a portal outside a Vue app.

I see, but as Linus has pointed target-el is "half-assed implementation" so i was just wondering if there was any special reason behind this choice. (I know he's improving it for v2.0)

Personally haven't found any styling/accessibility issues rendering portals inside the app, I just have an extra wrapper for content where the accessibility attributes can be toggled.

<!--App.vue-->

<template>
 <div id="app">
   <div id="wrapper" aria-attributes>
      <router-view />
   </div>

    <!-- portal targets -->
    <portal-target name="destination1" />
    <portal-target name="destination2" />
  </div>
<template>

But as i've said, i was just curious, thanks you for your time man!

Up to this current release, vue-a11y-dialog was rendered inside the app without the help of PortalVue. However, this turned out to essentially break the entire premise of a11y as the #app container, in which the dialog is a children, will be hidden.

I am not happy with a few implementation details as well, but eagerly waiting for the upcoming PortalVue release to (hopefully) get rid of them. For target-el, I simply followed the API documentation and stuck with it since it's going to stay and soon to be refactored majorly.

But as i've said, i was just curious, thanks you for your time man!

No worrries, always happy to answer any questions :)

That's is correct, but the second argument of A11yDialog constructor is an option to specify who is the content container (by default the siblings of dialog).

You already provide a prop to specify this element appRoot, and it isn't required to be "#app". This combined with a simple computedProp renderMode would allow you to optionally use the <portal-target> or target-el without any accessibility issue.

Here's your documentation example re-written to encapsulate all the thoughts of this thread

<template>
  <div id="app"> 
    <main id="content-wrapper-for-accessiblity">
      <!-- ... in real world, this would be router-view -->
      <button type="button" @click="openDialog">
        Open dialog
      </button>

      <a11y-dialog
        id="app-dialog"
        app-root="#content-wrapper-for-accessiblity"
        @dialog-ref="assignDialogRef"
        portal-target="my-dialogs"
        render-mode="fake-inside-prop"
      >
        <h1 slot="title">Your dialog title</h1>
        <div>
          <p>Your content</p>
        </div>
      </a11y-dialog>
    </main>

    <portal-target name="my-dialogs" multiple />
  </div>
</template>

Now this is just an alternative, a cheap one in terms of code. I know that with vue-portal 2.0 fortunately these will be problems of the past.

Sorry if i'm being annoying, i'm just a nerd and can't avoid a good positive discussion around code 😄

Hey @renatodeleao, just wanted to give you a quick update that PortalVue@2 is out and the newly introduced MountingPortal fixes the issue! I have a new release coming up either today or tomorrow. Then you will be able to use multiple portals as in your initial demo.

I've just released a new version, do you mind checking if it works for you?

@morkro works like charm, I'll leave here the updated demo for reference.

Thanks!