DaisyUI Nested collapse elements with dropdown menu

483 Views Asked by At

This is a follow up from this question. Now, I am using the solution from this question in my Vue component, updated the collapse part and now it's a nested collapse with some collapse elements inside.

The issue now is that if I put !overflow-visible on the main collapse, overriding it, the elements inside of it are not hidden anymore and they're overflowing from the collapse despite it being closed.

How can I solve this behaviour? I tried adding overflow-hidden to the children of the collapse but because of inheritance, the overflow-hidden doesn't do anything. Also one thing I noticed is that even though the collapse with the dropdown has a z-index of 99, it's not showing above everything else which it should do.

<template>
  <div
    v-for="index in 3"
    tabindex="0"
    class="collapse !overflow-visible collapse-plus z-0 rounded-lg border border-base-content bg-base-100 shadow-md md:w-[48.75%]"
    :class="collapse ? 'collapse-open' : 'collapse-close'"
  >
    <div
      class="collapse-title !overflow-hidden flex items-center text-lg font-medium"
      :class="collapse ? 'bg-primary' : 'bg-base-100'"
      @click="OnClick"
    >
      <div
        class="mr-3 grid h-[58px] !overflow-hidden w-[62px] place-content-center rounded-lg"
        :class="collapse ? 'bg-base-100' : 'bg-primary'"
      ></div>
      <div
        class="flex flex-col gap-1"
        :class="collapse ? 'text-base-100' : 'text-primary'"
      >
        Test
        <div class="badge badge-success rounded-[4px]">Active</div>
      </div>
    </div>
    <div class="collapse-content bg-base-200 !p-0 text-accent">
      <div
        tabindex="0"
        class="collapse collapse-open border border-base-300 bg-red-200 !overflow-visible"
      >
        <div class="collapse-title text-xl font-medium">
          I have collapse-open class
        </div>
        <div class="collapse-content !overflow-visible">
          <h2>HELLLERGLERL</h2>
          <h2>HELLLERGLERL</h2>
          <h2>HELLLERGLERL</h2>
          <h2>HELLLERGLERL</h2>
          <h2>HELLLERGLERL</h2>
          <h2>HELLLERGLERL</h2>
          <details class="dropdown dropdown-end z-[99]">
            <summary class="m-1 btn">open or close</summary>
            <ul
              class="p-2 shadow menu dropdown-content z-[98] bg-base-100 rounded-box w-52"
            >
              <li><a>Item 1</a></li>
              <li><a>Item 2</a></li>
              <li><a>Item 1</a></li>
              <li><a>Item 2</a></li>
              <li><a>Item 1</a></li>

              <li><a>Item 2</a></li>
            </ul>

            <div
              tabindex="0"
              class="collapse collapse-open border border-base-300 bg-blue-200 !overflow-visible"
            >
              <div class="collapse-title text-xl font-medium">
                I have collapse-open class
              </div>
              <div class="collapse-content">
                <details class="dropdown">
                  <summary class="m-1 btn">open or close</summary>
                  <ul
                    class="p-2 shadow menu dropdown-content z-[99] bg-base-100 rounded-box w-52"
                  >
                    <li><a>Item 1</a></li>
                    <li><a>Item 2</a></li>
                    <li><a>Item 1</a></li>
                    <li><a>Item 2</a></li>
                    <li><a>Item 1</a></li>
                    <li><a>Item 2</a></li>
                    <li><a>Item 1</a></li>
                    <li><a>Item 2</a></li>
                    <li><a>Item 1</a></li>
                    <li><a>Item 2</a></li>
                    <li><a>Item 1</a></li>
                    <li><a>Item 2</a></li>
                    <li><a>Item 1</a></li>
                    <li><a>Item 2</a></li>
                    <li><a>Item 1</a></li>
                    <li><a>Item 2</a></li>
                    <li><a>Item 1</a></li>
                    <li><a>Item 2</a></li>
                    <li><a>Item 1</a></li>
                    <li><a>Item 2</a></li>
                  </ul>
                </details>
              </div>
            </div>
          </details>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from "vue";
const collapse = ref(false);

function OnClick() {
  collapse.value = !collapse.value;
}
</script>

1

There are 1 best solutions below

1
On BEST ANSWER

You could consider using the <Teleport> built-in to render the drop-down menu outside the collapsible elements. This then negates the need to juggle overflow: visible/hidden. You would need to manually position the dropdowns yourself however, since they will no longer be inside the same parent as the dropdown buttons.

Here is a naïve example that demonstrates the concept:

const { createApp, ref } = Vue;

const dropdown = {
  setup() {
    const open = ref(false);
    const button = ref();
    const style = ref({});
    
    const toggle = () => {
      open.value = !open.value;
      if (open.value) {
        const rect = button.value.getBoundingClientRect();
        
        style.value.top = `${rect.top + window.scrollY}px`;
        style.value.left = `${rect.left + window.scrollX + rect.width}px`;
      }
    };
    
    return { open, toggle, button, style };
  },
  template: '#dropdown',
};

createApp({
  components: {
    dropdown,
  },
  setup() {
    const collapse = ref(false);

    function OnClick() {
      collapse.value = !collapse.value;
    }
    
    return { collapse, OnClick };
  }
}).mount('#app')
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.3.13/vue.global.prod.min.js" integrity="sha512-dJsT2VK9KxehzZYzxzUELznI6velu2pAOwpkL5jj4TQQhTNGXZUMup7aLqgqNwVPSUF/Ntcdfla3BEcfC7zwCw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/full.min.css" rel="stylesheet" type="text/css" />
<script src="https://cdn.tailwindcss.com/3.4.0"></script>

<div id="app">
  <div
    v-for="index in 3"
    tabindex="0"
    class="collapse collapse-plus z-0 rounded-lg border border-base-content bg-base-100 shadow-md md:w-[48.75%]"
    :class="collapse ? 'collapse-open' : 'collapse-close'"
  >
    <div
      class="collapse-title flex items-center text-lg font-medium"
      :class="collapse ? 'bg-primary' : 'bg-base-100'"
      @click="OnClick"
    >
      <div
        class="mr-3 grid h-[58px] w-[62px] place-content-center rounded-lg"
        :class="collapse ? 'bg-base-100' : 'bg-primary'"
      ></div>
      <div
        class="flex flex-col gap-1"
        :class="collapse ? 'text-base-100' : 'text-primary'"
      >
        Test
        <div class="badge badge-success rounded-[4px]">Active</div>
      </div>
    </div>
    <div class="collapse-content bg-base-200 !p-0 text-accent">
      <div
        tabindex="0"
        class="collapse collapse-open border border-base-300 bg-red-200"
      >
        <div class="collapse-title text-xl font-medium">
          I have collapse-open class
        </div>
        <div class="collapse-content">
          <h2>HELLLERGLERL</h2>
          <h2>HELLLERGLERL</h2>
          <h2>HELLLERGLERL</h2>
          <h2>HELLLERGLERL</h2>
          <h2>HELLLERGLERL</h2>
          <h2>HELLLERGLERL</h2>
          <dropdown>
            <ul
              class="p-2 shadow menu dropdown-content z-[98] bg-base-100 rounded-box w-52"
            >
              <li><a>Item 1</a></li>
              <li><a>Item 2</a></li>
              <li><a>Item 1</a></li>
              <li><a>Item 2</a></li>
              <li><a>Item 1</a></li>

              <li><a>Item 2</a></li>
            </ul>
            <template v-slot:content>
              <div
                tabindex="0"
                class="collapse collapse-open border border-base-300 bg-blue-200"
              >
                <div class="collapse-title text-xl font-medium">
                  I have collapse-open class
                </div>
                <div class="collapse-content">
                  <dropdown>
                    <ul
                      class="p-2 shadow menu dropdown-content z-[99] bg-base-100 rounded-box w-52"
                    >
                      <li><a>Item 1</a></li>
                      <li><a>Item 2</a></li>
                      <li><a>Item 1</a></li>
                      <li><a>Item 2</a></li>
                      <li><a>Item 1</a></li>
                      <li><a>Item 2</a></li>
                      <li><a>Item 1</a></li>
                      <li><a>Item 2</a></li>
                      <li><a>Item 1</a></li>
                      <li><a>Item 2</a></li>
                      <li><a>Item 1</a></li>
                      <li><a>Item 2</a></li>
                      <li><a>Item 1</a></li>
                      <li><a>Item 2</a></li>
                      <li><a>Item 1</a></li>
                      <li><a>Item 2</a></li>
                      <li><a>Item 1</a></li>
                      <li><a>Item 2</a></li>
                      <li><a>Item 1</a></li>
                      <li><a>Item 2</a></li>
                    </ul>
                  </dropdown>
                </div>
              </div>
            </template>
          </dropdown>
        </div>
      </div>
    </div>
  </div>
</div>

<template id="dropdown">
  <details class="dropdown dropdown-end z-[99]">
    <summary class="m-1 btn" @click="toggle" ref="button">open or close</summary>
    <Teleport to="body" v-if="open">
      <div class="absolute" :style="style">
        <slot></slot>
      </div>
    </Teleport>

    <slot name="content"></slot>
    </div>
  </details>
</template>