Search code examples
onclickvuejs3toggleexpand

Vue 3 single Collapse


Here my component that I work for. when I clicked on one of collapse button it will show both of it. please help me to find the solution that allow me to click on on the collapse component and only one that I clicked working for other is close.

const isShow = ref(false);
<script setup>
import { ArrowDownBold } from "@element-plus/icons-vue";
import { ArrowUpBold } from "@element-plus/icons-vue";

import { ref } from "vue";

const isShow = ref(false);
</script>
<template>
  <div class="py-4">
    <div class="relative flex flex-col justify-between w-full h-full bg-white">
      <div class="z-2 flex items-center bottom-[-200px] justify-center">
        <div
          @click="isShow = !isShow"
          class="flex justify-center bg-gray-200 py-1 px-2 text-sm z-50 text-gray-600 cursor-pointer space-x-2"
        >
          <p>VIEW DETAIL</p>
          <ArrowUpBold
            v-if="isShow"
            aria-hidden="true"
            class="w-4"
            color="rgba(75 85 99)"
          />
          <ArrowDownBold
            v-else
            aria-hidden="true"
            class="w-4"
            color="rgba(156 163 175)"
          />
        </div>
      </div>
      <div class="flex flex-col items-center">
        <Transition name="collapse1">
          <div
            class="w-full overflow-hidden h-auto top-[12px] bg-gray-200"
            v-if="isShow"
          >
            <h1>Collapse 1</h1>
          </div>
        </Transition>
      </div>
    </div>
  </div>

  <div class="py-4">
    <div class="relative flex flex-col justify-between w-full h-full bg-white">
      <div class="z-2 flex items-center bottom-[-200px] justify-center">
        <div
          @click="isShow = !isShow"
          class="flex justify-center bg-gray-200 py-1 px-2 text-sm z-50 text-gray-600 cursor-pointer space-x-2"
        >
          <p>VIEW DETAIL</p>
          <ArrowUpBold
            v-if="isShow"
            aria-hidden="true"
            class="w-4"
            color="rgba(75 85 99)"
          />
          <ArrowDownBold
            v-else
            aria-hidden="true"
            class="w-4"
            color="rgba(156 163 175)"
          />
        </div>
      </div>
      <div class="flex flex-col items-center">
        <Transition name="collapse1">
          <div
            class="w-full overflow-hidden h-auto top-[12px] bg-gray-200"
            v-if="isShow"
          >
            <h1>Collapse 2</h1>
          </div>
        </Transition>
      </div>
    </div>
  </div>
</template>

Solution

  • You have a shared variable for the both collapsible sections so they are collapsed/expanded together. You could make the variable an object and use its props as an expanded flag.

    But in your case you should create a component for the collapsible detail sections:

    <script setup>
    import { ArrowDownBold } from "@element-plus/icons-vue";
    import { ArrowUpBold } from "@element-plus/icons-vue";
    import { CollapsibleDetails } from './CollapsibleDetails.vue';
    
    </script>
    <template>
      <CollapsibleDetails><h1>Collapse 1</h1></CollapsibleDetails>
      <CollapsibleDetails><h1>Collapse 2</h1></CollapsibleDetails>
    </template>
    

    CollapsibleDetails.vue:

    <script setup>
    
    import {ref} from 'vue';
    
    const isShow = ref(false);
    
    </script>
    <template>
      <div class="py-4">
        <div class="relative flex flex-col justify-between w-full h-full bg-white">
          <div class="z-2 flex items-center bottom-[-200px] justify-center">
            <div
              @click="isShow = !isShow"
              class="flex justify-center bg-gray-200 py-1 px-2 text-sm z-50 text-gray-600 cursor-pointer space-x-2"
            >
              <p>VIEW DETAIL</p>
              <ArrowUpBold
                v-if="isShow"
                aria-hidden="true"
                class="w-4"
                color="rgba(75 85 99)"
              />
              <ArrowDownBold
                v-else
                aria-hidden="true"
                class="w-4"
                color="rgba(156 163 175)"
              />
            </div>
          </div>
          <div class="flex flex-col items-center">
            <Transition name="collapse1">
              <div
                class="w-full overflow-hidden h-auto top-[12px] bg-gray-200"
                v-if="isShow"
              >
                <slot></slot>
              </div>
            </Transition>
          </div>
        </div>
      </div>
    </template>