excid3 / tailwindcss-stimulus-components

A set of StimulusJS components for TailwindCSS apps similar to Bootstrap JS components.
https://excid3.github.io/tailwindcss-stimulus-components/
MIT License
1.35k stars 136 forks source link

Dropdown ignores enter animation #154

Closed ghost closed 1 year ago

ghost commented 2 years ago

I noticed that the dropdown component doesn't seem to properly animate the transition from its invisible to visible state. After a few hours of fiddling around, I have yet to find the cause or a potential solution.

I've been closely following the README and set up my dropdown as follows:

  <div
    class="relative"
    data-controller="dropdown"
    data-dropdown-invisible-class="opacity-0 scale-95"
    data-dropdown-visible-class="opacity-100 scale-100"
    data-dropdown-entering-class="ease-out duration-300"
    data-dropdown-enter-timeout="150"
    data-dropdown-leaving-class="ease-in duration-300"
    data-dropdown-leave-timeout="150"
  >
    <div
      class="flex hover:bg-neutral-200 p-2 rounded-xl"
      role="button"
      tabindex="0"
      data-action="click->dropdown#toggle click@window->dropdown#hide"
      data-dropdown-target="button"
    >
      Dropdown
    </div>
    <div
      class="absolute max-w-md whitespace-nowrap left-1/2 -translate-x-1/2 mt-2 transform transition-all hidden opacity-0 scale-95"
      data-dropdown-target="menu"
    >
      <div class="relative bg-white shadow rounded p-5">
        <div class="absolute w-3 h-3 bg-white -top-1 left-1/2 -translate-x-1/2 rotate-45 rounded-sm"></div>
        <span>Content</span>
      </div>
    </div>
  </div>

Curiously enough, the leaving animation works like a charm.

Please note that this also seems to be the case for the dropdown example in the tailwindcss-stimulus-components demo:

CleanShot 2022-04-16 at 10 22 23

Opening is instant, closing is animated.

Any ideas?

chrise86 commented 2 years ago

@brueggemann-erik did you manage to resolve this? I'm also seeing this.

mitch15 commented 2 years ago

It looks like a class of .hidden is applied and removed when opening and closing the menu - this is essentially display:none which as far as I know can't be animated.

If you specify a different class via the data-dropdown-class attribute such as .invisible you can set this to something like visibility: hidden instead. You'll also need to add this same class to the div with the class of data-dropdown-target="menu"

It's not exactly the same but the in and out transition effects seem to work and doesn't affect keyboard navigation. I did have some problems with animating the scale effect in with Tailwind classes, so I eventually ended up writing these in plain CSS and it seemed to work (not shown below)

 <div
    class="relative"
    data-controller="dropdown"
    data-dropdown-class="invisible"
    data-dropdown-invisible-class="opacity-0 scale-95"
    data-dropdown-visible-class="opacity-100 scale-100"
    data-dropdown-entering-class="ease-out duration-500"
    data-dropdown-enter-timeout="500"
    data-dropdown-leaving-class="ease-in duration-500"
    data-dropdown-leave-timeout="500"
  >
  <div
      class="flex hover:bg-neutral-200 p-2 rounded-xl"
      role="button"
      tabindex="0"
      data-action="click->dropdown#toggle click@window->dropdown#hide"
    data-dropdown-target="button"
    >
    Dropdown
  </div>
  <div
      class="absolute max-w-md whitespace-nowrap left-1/2 -translate-x-1/2 mt-2 transform transition-all invisible opacity-0 scale-95"
      data-dropdown-target="menu"
    >
    <div class="relative bg-white shadow rounded p-5">
      <div class="absolute w-3 h-3 bg-white -top-1 left-1/2 -translate-x-1/2 rotate-45 rounded-sm"></div>
      <a href="#">Example Link 1</a>
      <a href="#">Example Link 2</a>
      <a href="#">Example Link 3</a>
    </div>
  </div>
</div>
seanharmer commented 2 years ago

Same issue with slideovers too. Can't use this work around with a slideover though as it removes the class used to overide the toggle at https://github.com/excid3/tailwindcss-stimulus-components/blob/master/src/slideover.js#L39

Maybe I need to rethink my approach as I can make the menu exit animation work but the overlay does not animate as hoped on exit. On entry it's instantaneous.

mitch15 commented 2 years ago

@seanharmer you should still be able to use a similar workaround with the slideover from my experimenting. I extracted the animating styles into their own classes to make it a bit easier to reason with:

<style>
  .menu-in {
    opacity: 100;
    transform: translateX(0%);
    transition: 0.3s all;
  }

  .menu-out {
    opacity: 0;
    transform: translateX(-100%);
    transition: 0.3s all;
  }

  .overlay-out {
    opacity: 0;
    transition: 0.3s all;
  }

  .overlay-in {
    opacity: 100;
    transition: 0.5s all;
  }
 </style>

And then adding these classes to the invisible / visible class attributes and also adding the data-slideover-class (this will override the "hidden" class being applied which is causing the abrupt transitions). I've set a slight delay between the menu sliding out and the overlay fading but you could remove it if wanted.

 <div 
  class="container mx-auto p-8" 
  data-controller="slideover" 
  data-slideover-class="invisible"
  data-slideover-open-value="false" 
  data-slideover-invisible-class="menu-out,overlay-out"
  data-slideover-visible-class="menu-in,overlay-in" 
  data-slideover-enter-timeout="300,0"
  data-slideover-leave-timeout="300,0" 
  data-slideover-active-target="#slideover-target">
    <!-- begin sidebar/slideover -->
    <div id="sidebar-mobile">
      <div data-slideover-target="overlay" class="overlay-out fixed inset-0 flex z-40">
        <div class="fixed inset-0">
          <div class="absolute inset-0 bg-gray-600 opacity-75"></div>
        </div>
        <div id="slideover-target" data-slideover-target="menu" class="menu-out relative flex-1 flex flex-col max-w-xs w-full pt-5 pb-4 bg-gray-800">
          <div class="absolute top-0 right-0 -mr-14 p-1">
            <button data-action="slideover#toggle" class="flex items-center justify-center h-12 w-12 rounded-full focus:outline-none focus:bg-gray-600" aria-label="Close sidebar">
              <svg class="h-6 w-6 text-white" stroke="currentColor" fill="none" viewBox="0 0 24 24">
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
              </svg>
            </button>
          </div>
          <div class="flex-shrink-0 flex items-center px-4">
            <h1 class="text-white text-2xl font-bold">Sidebar</h1>
          </div>
          <div class="mt-5 flex-1 h-0 overflow-y-auto">
            <nav class="px-2 space-y-1">
            </nav>
          </div>
        </div>
        <div class="flex-shrink-0 w-14">
          <!-- Dummy element to force sidebar to shrink to fit close icon -->
        </div>
      </div>
    </div>

    <!-- end sidebar/slideover -->
      <button data-action="click->slideover#toggle click@window->slideover#hide"
        class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-3 px-6 rounded">
        <span>Open Slideover</span>
      </button>
  </div>

https://user-images.githubusercontent.com/6477705/173833150-a1df999a-5895-4c87-b82d-3476059b365d.mp4

excid3 commented 1 year ago

We've replaced the animation system completely in v4.