Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(teleport): correctly select overlay container in shadow DOM #20277

Closed

Conversation

cgodo
Copy link
Contributor

@cgodo cgodo commented Aug 3, 2024

Description

When VOverlay is mounted in the Shadow DOM, it passes correctly the shadowRoot element to the teleport composable. Then the teleport composable checks for an existing v-overlay-container using :scope > .v-overlay-container selector.

However, as confirmed by css specs discussion, :scope selector doesn't select anything when used on a ShadowRoot element, so an existing overlay container is never found and it is created and appended again.

The solution is to use :host > .v-overlay-container selector when the element is an instance of ShadowRoot.

fixes #20276

Markup:

<template>
  <v-menu v-bind="$attrs" location="right">
    <template #activator="{ props }">
      <v-btn v-bind="props" class="ma-5">Normal Menu</v-btn>
    </template>
    <v-list>
      <v-menu location="right">
        <template #activator="{ props }">
          <v-list-item v-bind="props" title="Submenu" />
        </template>
        <v-list>
          <v-list-item title="Submenu item" />
          <v-list-item title="Submenu item" />
        </v-list>
      </v-menu>
    </v-list>
  </v-menu>

  <div ref="shadow" />
</template>

<script>
  import { createApp, h } from 'vue'
  import vuetify from './vuetify'
  import { VBtn, VList, VListItem, VMenu } from 'vuetify/src/components'

  export default {
    name: 'Playground',
    setup () {
      return {

      }
    },
    mounted () {
      const shadowRoot = this.$refs.shadow.attachShadow({ mode: 'open' })
      const shadowApp = document.createElement('div')
      shadowApp.id = 'shadow-app'
      shadowRoot.appendChild(shadowApp)
      document.querySelectorAll('style').forEach(styleElement => {
        shadowRoot.appendChild(styleElement.cloneNode(true))
      })

      createApp({
        render: () => h(VMenu, { location: 'right' }, {
          activator: ({ props }) => h(VBtn, { ...props, class: 'ma-5' }, 'Shadow Menu'),
          default: () => [
            h(VList, {}, () => [
              h(VMenu, { location: 'right' }, {
                activator: ({ props }) => h(VListItem, { ...props, title: 'Submenu' }),
                default: () => [
                  h(VList, {}, () => [
                    h(VListItem, { title: 'Submenu item' }),
                    h(VListItem, { title: 'Submenu item' }),
                  ]),
                ],
              }),
            ]),
          ],
        }),
      })
        .use(vuetify)
        .mount(shadowApp)
    },
  }
</script>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Bug Report][3.6.14] Multiple VOverlay containers are created in Shadow DOM
1 participant