Stimulus.js를 사용한 Tailwind 전환 효과 진입/퇴장

TailwindUI의 팬으로서 저는 Apline.js 또는 Vue.js를 사용하지 않고 제안된 enter/leave를 지원하는 것이 불가능하다는 사실에 실망했습니다. Tailwind 팀은 반응 지원을 위해 자체 전환 구성 요소도 구축했습니다. Ruby on Rails 및 Stimulus.js로 작업하기 저는 프로젝트를 "핵심"레일에 가깝게 유지하고 싶었습니다. 전환을 위해 Alpine.js를 포함하거나 Vue.js로 전환하는 것이 최적이라고 생각하지 않았습니다. 그만한 가치는 Alpine과 Vue가 모두 훌륭하다고 생각합니다!

처음에는 노력하지 않았습니다. 약간의 연구와 몇 개의 YouTube 동영상이 나중에 부족했습니다. 나는 단순히 요소를 숨기거나 표시하거나 animate.css와 같은 것에서 일반 애니메이션을 적용하는 것으로 결정했습니다. 하지만 구현이 불가능하다는 사실을 받아들일 수 없었습니다. 게다가 별로 좋아 보이지도 않았다. 나는 조금 더 깊이 파고 들었고 이것을 발견했습니다 amazing article. 전환이 구현되는 방식을 이해하려면 이 책을 읽는 것이 좋습니다. 나는 많은 것을 배웠고 저자에게 많은 신용을 제공합니다!

기사에서 교훈을 얻어 편리한 작은 npm 패키지el-transition로 추상화할 수 있었습니다. 이 글을 쓰는 동안 el-transition 언론에서 뜨겁습니다. 검토하고 기여해 주세요!


mmccall10 / 전자 전환


Enter/Leave 전환 적용




이 패키지를 사용하여 TailwindUI 전환 효과를 구현할 것입니다!

이 예에서는 드롭다운 구성 요소를 빌드해 보겠습니다. 여기에서 tailwind 마크업을 찾을 수 있습니다here.

시작하기 전에 el-transition 패키지를 설치하십시오.

$ yarn add el-transition

코딩 시간



다음은 TailwindUI 라이브러리의 드롭다운 구성 요소를 직접 복사한 것입니다. 제안된 입력/퇴장 전환 클래스를 지정하는 주석을 확인하십시오.

<div class="relative inline-block text-left">
  <div>
    <span class="rounded-md shadow-sm">
      <button type="button" class="inline-flex justify-center w-full rounded-md border border-gray-300 px-4 py-2 bg-white text-sm leading-5 font-medium text-gray-700 hover:text-gray-500 focus:outline-none focus:border-blue-300 focus:shadow-outline-blue active:bg-gray-50 active:text-gray-800 transition ease-in-out duration-150" id="options-menu" aria-haspopup="true" aria-expanded="true">
        Options
        <svg class="-mr-1 ml-2 h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
          <path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" />
        </svg>
      </button>
    </span>
  </div>

  <!--
    Dropdown panel, show/hide based on dropdown state.

    Entering: "transition ease-out duration-100"
      From: "transform opacity-0 scale-95"
      To: "transform opacity-100 scale-100"
    Leaving: "transition ease-in duration-75"
      From: "transform opacity-100 scale-100"
      To: "transform opacity-0 scale-95"
  -->
  <div class="origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg">
    <div class="rounded-md bg-white shadow-xs">
      <div class="py-1" role="menu" aria-orientation="vertical" aria-labelledby="options-menu">
        <a href="#" class="block px-4 py-2 text-sm leading-5 text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900" role="menuitem">Account settings</a>
        <a href="#" class="block px-4 py-2 text-sm leading-5 text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900" role="menuitem">Support</a>
        <a href="#" class="block px-4 py-2 text-sm leading-5 text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900" role="menuitem">License</a>
        <form method="POST" action="#">
          <button type="submit" class="block w-full text-left px-4 py-2 text-sm leading-5 text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900" role="menuitem">
            Sign out
          </button>
        </form>
      </div>
    </div>
  </div>
</div>

이제 드롭다운 요소에 연결할 수 있는 드롭다운 자극 컨트롤러를 만들어 보겠습니다. 두 개의 대상buttonmenutoggleMenu 함수를 추가합니다.

// dropdown_controller.js
import {Controller} from "stimulus"

export default class extends Controller {
    static targets = ["menu", "button"]

    toggleMenu() {
        if (this.menuTarget.classList.contains('hidden')) {
            // enter transition
        } else {
            // leave transition
        }
    }
}

이제 컨트롤러를 드롭다운에 연결할 수 있습니다.

<!-- add dropdown controller -->
<div data-controller="dropdown" class="relative inline-block text-left">
  <div>
    <span class="rounded-md shadow-sm">

      <!-- Add button target and click action -->
      <button type="button" data-target="dropdown.button" data-action="click->dropdown#toggleMenu" class="inline-flex justify-center w-full rounded-md border border-gray-300 px-4 py-2 bg-white text-sm leading-5 font-medium text-gray-700 hover:text-gray-500 focus:outline-none focus:border-blue-300 focus:shadow-outline-blue active:bg-gray-50 active:text-gray-800 transition ease-in-out duration-150" id="options-menu" aria-haspopup="true" aria-expanded="true">
        Options
        <svg class="-mr-1 ml-2 h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
          <path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" />
        </svg>
      </button>
    </span>
  </div>

  <!-- add menu target -->
  <div data-target="dropdown.menu" class="origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg">
    <div class="rounded-md bg-white shadow-xs">
      <div class="py-1" role="menu" aria-orientation="vertical" aria-labelledby="options-menu">
        <a href="#" class="block px-4 py-2 text-sm leading-5 text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900" role="menuitem">Account settings</a>
        <a href="#" class="block px-4 py-2 text-sm leading-5 text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900" role="menuitem">Support</a>
        <a href="#" class="block px-4 py-2 text-sm leading-5 text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900" role="menuitem">License</a>
        <form method="POST" action="#">
          <button type="submit" class="block w-full text-left px-4 py-2 text-sm leading-5 text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900" role="menuitem">
            Sign out
          </button>
        </form>
      </div>
    </div>
  </div>
</div>

이제 컨트롤러가 연결되었으므로 제안된 전환을 구현해 보겠습니다.

 <!--
    Dropdown panel, show/hide based on dropdown state.

    Entering: "transition ease-out duration-100"
      From: "transform opacity-0 scale-95"
      To: "transform opacity-100 scale-100"
    Leaving: "transition ease-in duration-75"
      From: "transform opacity-100 scale-100"
      To: "transform opacity-0 scale-95"
  -->

이를 위해 el-transitondata-transition-* 속성 또는 애니메이션 클래스를 기대합니다. 우리는 Apline.js가 작동하는 방식과 더 일치하는 데이터 속성을 사용할 것입니다. 다음은 전환이 선언된 업데이트된 html입니다.

<div data-controller="dropdown" class="relative inline-block text-left">
  <div>
    <span class="rounded-md shadow-sm">
      <button type="button" data-target="dropdown.button" data-action="click->dropdown#toggleMenu" class="inline-flex justify-center w-full rounded-md border border-gray-300 px-4 py-2 bg-white text-sm leading-5 font-medium text-gray-700 hover:text-gray-500 focus:outline-none focus:border-blue-300 focus:shadow-outline-blue active:bg-gray-50 active:text-gray-800 transition ease-in-out duration-150" id="options-menu" aria-haspopup="true" aria-expanded="true">
        Options
        <svg class="-mr-1 ml-2 h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
          <path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" />
        </svg>
      </button>
    </span>
  </div>

<!-- add transition data attributes. -->
<div class="origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg hidden"
       data-target="dropdown.menu"
       data-transition-enter="transition ease-out duration-100"
       data-transition-enter-start="transform opacity-0 scale-95"
       data-transition-enter-end="transform opacity-100 scale-100"
       data-transition-leave="transition ease-in duration-75"
       data-transition-leave-start="transform opacity-100 scale-100"
       data-transition-leave-end="transform opacity-0 scale-95"
  >
    <div class="rounded-md bg-white shadow-xs">
      <div class="py-1" role="menu" aria-orientation="vertical" aria-labelledby="options-menu">
        <a href="#" class="block px-4 py-2 text-sm leading-5 text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900" role="menuitem">Account settings</a>
        <a href="#" class="block px-4 py-2 text-sm leading-5 text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900" role="menuitem">Support</a>
        <a href="#" class="block px-4 py-2 text-sm leading-5 text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900" role="menuitem">License</a>
        <form method="POST" action="#">
          <button type="submit" class="block w-full text-left px-4 py-2 text-sm leading-5 text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900" role="menuitem">
            Sign out
          </button>
        </form>
      </div>
    </div>
  </div>
</div>

마지막으로 입력/퇴장 전환 효과를 실행하도록 자극 드롭다운 컨트롤러를 업데이트할 수 있습니다.

import {Controller} from "stimulus"
// import the enter leave functions
import {enter, leave} from 'el-transition'; 

export default class extends Controller {
    static targets = ["menu", "button"]

    // call the enter and leave functions
    toggleMenu() {
        if(this.menuTarget.classList.contains('hidden')) {
            enter(this.menuTarget)
        } else {
            leave(this.menuTarget)
        }
    }
}

그게 다야!

여기에서 데모를 찾을 수 있습니다.





결론



TailwindUI가 제안한 전환 효과를 지원할 수 있게 되어 기쁩니다. 팀에서 많은 관심을 기울이고 멋지게 보이기 때문입니다! 이 예는 stimulus.js에만 적용되지만 el-transition는 프레임워크에 구애받지 않습니다.

좋은 웹페이지 즐겨찾기