Search code examples
vuejs3tailwind-csscss-transitionsvuejs-transition

Add transition to dynamic hidden attribute using tailwindcss and vuejs


I am create UI layout using tailwind css and nuxt.
Where sidebar is always visible at md breakpoint
and hidden on mobile devices which is only visible when menu button is clicked.

This works fine as when button is clicked sidebar is shown, as i am setting and removing hidden class
However I want to add transition when it is show

Below is current code

<template>

   <!-- backdrop -->
   <div v-if="sidebarOpen" class="fixed md:hidden bg-black w-full min-h-dvh opacity-20" @click="hideSideBar()">
   </div>


   <div 
      :class="{ hidden: !sidebarOpen}" //<--- here i am setting this
      class="w-64 group md:block fixed  transition-all h-dvh shadow-md shadow-gray-400 shadow-x-1 mr-1 flex-none md:w-14 md:hover:w-64 overflow-hidden">
      <div class=" p-2 flex bg-violet-500 ">
         <Icon name="🚀" size="38" />
      </div>
      <div class="overflow-y-auto h-full">
         <div class="h-full px-3 py-4 overflow-y-auto bg-white dark:bg-gray-800 pb-12">
            <ul class="space-y-2 font-medium">
               <li>
                  <a href="#"
                     class="flex items-center p-2 text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700 group">
                     <div>
                        <Icon name="mdi:view-grid-plus-outline" class="text-red-600" size="1.2rem" />
                     </div>
                     <span class="flex-1 md:hidden group-hover:block ms-3 whitespace-nowrap">Kanban</span>
                     <span
                        class="inline-flex md:hidden group-hover:block items-center justify-center px-2 ms-3 text-sm font-medium text-gray-800 bg-gray-100 rounded-full dark:bg-gray-700 dark:text-gray-300">Pro</span>
                     <span
                        class="inline-flex items-center justify-center ms-3 text-sm font-medium md:hidden group-hover:block">
                        <Icon name="formkit:down" class="text-red-600" size="1.2rem" />
                     </span>
                  </a>
               </li>
               <li>
                  <a href="#"
                     class="flex items-center p-2 text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700 group">
                     <div>
                        <Icon name="mdi:view-grid-plus-outline" class="text-red-600" size="1.2rem" />
                     </div>
                     <span class="flex-1  md:hidden group-hover:block ms-3 whitespace-nowrap">Kanban</span>
                     <span
                        class="inline-flex md:hidden group-hover:block items-center justify-center px-2 ms-3 text-sm font-medium text-gray-800 bg-gray-100 rounded-full dark:bg-gray-700 dark:text-gray-300">Pro</span>
                  </a>
               </li>
            </ul>
         </div>
      </div>

   </div>


</template>

<script setup>

const sidebarOpen = useState('sidebarOpen')

function hideSideBar() {
   sidebarOpen.value = false;
}

</script>

Tried using https://vuejs.org/guide/built-ins/transition
transition with :key it does not work.

Demo: https://stackblitz.com/edit/nuxt-starter-evxfmn?file=app.vue


Solution

  • Reminbering display: none can't create a transition, so using Vue's transition component and v-if instead of class="hide".

    Edit: using transformX instead of class="hide".


    Here is a working repro!