티스토리 뷰

반응형

 

https://tailwindcss.com/

 

 

Tailwind CSS - Rapidly build modern websites without ever leaving your HTML.

Documentation for the Tailwind CSS framework.

tailwindcss.com

Tailwind css 는 클래스 속성명이 매우 직관적이라는 장점덕분에 개발속도를 매우 빠르게할 수 있는 CSS Framework 중 하나다. Bootstrap 만 사용하다가 뭔가 다른게 없나 찾아보던 과정에 찾게된 css 인데 추구하는 방향이 매우 잘맞아 사용하기로 했다. 그래서 가볍게 Docs 를 살펴보고 Components 로 넘어갔는데...

 

? Pricing? 이게 뭐람?  다른 css framework 처럼 사용할 수 있는 기본 컴포넌트들이 정의가 되어있는게 아니라 템플릿 느낌으로 여러 형태의 사용례가 있고 그것들 중 일부는 무료이나 일부는 사진만 있는것이 아닌가. 전체를 다 살펴보며 일단 나쁘지 않다 그냥 사자. 라고 마음먹고 가격을 보니 300 달러다. 다른게 없나 고민하다가 비용으로 떨구기로 결정하고 바로 구매해서 사용하기로 한다.

 

구매전에 Doc 를 보면서 react, vue, html 버전이 있구나라고 적당히 이해하고 구매를 했는데,

your own JS 를 더 자세히 읽어봤어야 하는 생각이 들었다. 생각보다 여러 컴포넌트들 특히 메뉴가 열린다든지 상호작용이 있는 부분들이 많아서 꽤 My own JS 를 결합해야 한다는 사실을 알고나서, 이걸 해결한 사람은 없을까 또 구글링을 시작한다.

 

찾아보니 TailwindUI 의 HTML 버전을 사용할  때는 AlpineJS 를 사용해서 손쉽게 할 수 있다는 글을 찾는다.

https://alpinejs.dev/

 

Alpine.js

Alpine is a rugged, minimal tool for composing behavior directly in your markup. Think of it like jQuery for the modern web. Plop in a script tag and get going. Alpine is a collection of 15 attributes, 6 properties, and 2 methods. There is no better way to

alpinejs.dev

 

Alpine 은 빌드 단계가 없고 라이브러리 크기는 4kb 정도 밖에 안되는 프레임워크다. 드롭다운이나 사이드바, 탭, 이미지 선택 등 최소한의 JS 가 필요한 경우에 사용하기 적합하다.

 

Tailwind UI + AlpineJS

 

일단 Alpine JS 를 Html 에 포함 시키는 것 부터 시작한다.

<html>
  <head>
    ...
 
    <script src="//unpkg.com/alpinejs" defer></script>
  </head>
  ...
</html>

head 안에 alpinejs 를 import 할 것. 하고나면 TailwindUI 에서 사용하는 주석대로 적용해주면 작동한다.

 

https://tailwindui.com/documentation#html-accessibility

 

Tailwind UI

Beautiful UI components by the creators of Tailwind CSS.

tailwindui.com

 

 

위의 예시를 기준으로 사용해보면, 클래스를 Dynamic 하게 구성하는 방법과 Transition 방법이 예시로 나와있다. 일단 Dynamic Classes 부터 살펴보면,

 

 

<!-- On: "bg-indigo-600", Off: "bg-gray-200" -->
<span aria-checked="false" class="bg-gray-200 relative inline-block flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:shadow-outline" role="checkbox" tabindex="0">
  <!-- On: "translate-x-5", Off: "translate-x-0" -->
  <span aria-hidden="true" class="translate-x-0 inline-block h-5 w-5 rounded-full bg-white shadow transform transition ease-in-out duration-200"></span>
</span>

유로 Component 들의 코드을 보면 이런 방식으로 주석이 달려있는데 이걸 그대로 Alpine JS 에 맞게 옮겨주면 된다.

 

<span
  x-data="{ isOn: false }"
  @click="isOn = !isOn"
  :aria-checked="isOn"
  :class="{'bg-indigo-600': isOn, 'bg-gray-200': !isOn }"
  class="bg-gray-200 relative inline-block flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:shadow-outline"
  role="checkbox"
  tabindex="0"
>
  <span
    aria-hidden="true"
    :class="{'translate-x-5': isOn, 'translate-x-0': !isOn }"
    class="translate-x-0 inline-block h-5 w-5 rounded-full bg-white shadow transform transition ease-in-out duration-200"
  ></span>
</span>

이렇게. 자세히 살펴보면

 

<!-- On: "bg-indigo-600", Off: "bg-gray-200" -->

 x-data="{ isOn: false }"
  @click="isOn = !isOn"
  :aria-checked="isOn"
  :class="{'bg-indigo-600': isOn, 'bg-gray-200': !isOn }"

저 주석이 이렇게 바뀐것으로 보면 된다. 총 3가지를 작성해주면 되는데, 각 상황을 기록할 변수, 변수를 변경하는 방법, 변경에 따른 변화. 이렇게 3가지를 작성하면 된다.

 

각 상황을 기록할 변수

x-data 라는 것은 alpineJS 에서 새로운 Alpine 컴포넌트와 값을 할당할 때 쓰는 방법인데, x-data="{ isOn: false }" 는 isOn 이라는 변수를 만들고 최초에 false 로 할당하자 라는 의미이고,

 

변수를 변경하는 방법

@click 은 클릭시 실행할 부분을 정의한다. 위의 예시에서는 클릭시 isOn의 값을 false 에서 true로,  true 에서 false 로 변경한다.

 

변경에 따른 변화

aria-checked 는 해당 엘리먼트가 선택되었는지 아닌지를 나타내는 속성인데, :aria-checked 로 작성 시 alpineJS 에서 자체적으로 변경할 수 있는 형태로 변경되며 "isOn" 을 단순 문자열이 아닌 x-data 에서 선언한 isOn 이라는 변수를 사용하게 해준다. 그래서 최초 isOn 이 false 로 된 상황에서라면 aria-checked 값은 false 로 설정되었다가 클릭 시 true 로 변경해준다.

:class 또한 class 를 alpineJS 에서 설정가능하게 선언하는 방식인데, isOn 값에 따라 전자를 추가할지 후자를 추가할지 결정하게 해준다.

 

그래서 다른곳에 적용할 때도 on off 상태를 저장할 수 있는 변수를 x-data 를 통해 선언하고 클릭시 변경시키고 싶다는 것을 알려주고, on off 에 따라 어떤 행동을 할 지 선언해주면 된다.

 

처음에 Doc 를 보면 당황스럽긴한데 하나하나 살펴보면 별거 없다. 가볍게 사용하기 위해 만든 JS FrameWork 이기 때문에 어렵지 않다.

 

 

예제를 하다 더 살펴보면 

<div class="relative ...">
  <button type="button" class="...">
    Options
  </button>

  <!--
    Show/hide this element based on the dropdown state

    Entering: "transition ease-out duration-100 transform"
      From: "opacity-0 scale-95"
      To: "opacity-100 scale-100"
    Closing: "transition ease-in duration-75 transform"
      From: "opacity-100 scale-100"
      To: "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">
      <!-- Snipped  -->
    </div>
  </div>
</div>

이 부분 중 저 Show/Hide 부분이 사용되면 되는건데,

 

<div x-data="{ isOpen: false }" class="relative ...">
  <button type="button" @click="isOpen = !isOpen" class="...">
    Options
  </button>

  <div
    x-show="isOpen"
    x-transition:enter="transition ease-out duration-100 transform"
    x-transition:enter-start="opacity-0 scale-95"
    x-transition:enter-end="opacity-100 scale-100"
    x-transition:leave="transition ease-in duration-75 transform"
    x-transition:leave-start="opacity-100 scale-100"
    x-transition:leave-end="opacity-0 scale-95"
    class="origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg"
  >
    <div class="rounded-md bg-white shadow-xs">
      <!-- Snipped  -->
    </div>
  </div>
</div>

다음과 같이 alpineJS 에 맞춰 적용해주면 된다.

 

<div class="relative ...">
  <button type="button" class="...">
    Options
  </button>
  
  >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  
  <div x-data="{ isOpen: false }" class="relative ...">
  <button type="button" @click="isOpen = !isOpen" class="...">
    Options
  </button>

이렇게 되는데, 일단 show, hide 를 하기 위해서 어떤 부분이 클릭되는지를 살펴보면, 중간에 있는 button 을 눌렀을 때 보여지게 하거나 안보이게 하거나 하고 싶은 상황이다. 그러면 위와 동일하게 isOpen 이라는 변수를 사용해서 true false 를 변경해가면 될텐데, 문제는 이 isOpen 이라는 변수를 어디에서 선언해야하는가 이다.

 

일단 isOpen 을 조종하는 버튼과 그 버튼으로 보이게하고 숨길 밑의 div. 이 두가지가 같은 값을 갖는 isOpen 을 공유해야한다. 그렇기 때문에 단순히 Button 에 x-data 로 isOpen 을 선언하는게 아니라 두 엘리먼트를 포함하는 상위 div 에 isOpen을 선언한다.

 

그럼 위에서와 같이 변수 선언, 변수 변경 방법 을 상위 div 와 버튼에 추가를 해주고. 변수에 따른 변화 부분을 추가해주면 되는데, 이 때 주석을 확인한다.

 

<!--
    Show/hide this element based on the dropdown state

    Entering: "transition ease-out duration-100 transform"
      From: "opacity-0 scale-95"
      To: "opacity-100 scale-100"
    Closing: "transition ease-in duration-75 transform"
      From: "opacity-100 scale-100"
      To: "opacity-0 scale-95"
  -->
  <div class="origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg">
  
  >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  
  <div
    x-show="isOpen"
    x-transition:enter="transition ease-out duration-100 transform"
    x-transition:enter-start="opacity-0 scale-95"
    x-transition:enter-end="opacity-100 scale-100"
    x-transition:leave="transition ease-in duration-75 transform"
    x-transition:leave-start="opacity-100 scale-100"
    x-transition:leave-end="opacity-0 scale-95"
    class="origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg"
  >

 

일단 첫째줄의 x-show 는 해당 엘리먼트의 visibility 를 설정하는 것이다.

그리고 주석의 Entering, From, To 를 순서대로 x-transition:enter, :enter-start, :enter-end 에 작성해주고

그다음 주석의 Closing, From, To 를 순서대로 x-transition:leave, :leave-start, :leave-end 에 작성해주면 된다.

 

간단하게.

 

그리고 예시에는 없지만 일반적으로 버튼 클릭을 통해 보여진 div 엘리먼트가 아닌 부분을 클릭했을 때 해당 div 를 사라지게 하기 위해서 @click.away 를 추가하자.

@click.away = "isOpen = false"

반응형

'Python > django' 카테고리의 다른 글

CKeditor 5 - django free wysiwyg text editor - 라이센스  (0) 2022.04.23
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함