티스토리 뷰
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 를 사용해서 손쉽게 할 수 있다는 글을 찾는다.
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
위의 예시를 기준으로 사용해보면, 클래스를 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
- 가평캠핑
- 가평여행
- 캠핑장추천
- SeoulTravel
- 가족여행
- 파이썬
- 글램핑
- 반려견캠핑
- 계곡캠핑
- 백준
- 자연힐링
- 여름휴가
- 카카오
- 커플여행
- 영월캠핑
- Oracle
- 영월여행
- sql
- 강원도여행
- 가족캠핑
- 여름캠핑
- 서울근교캠핑
- bukhansannationalpark
- Koreancuisine
- 머신러닝
- 알고리즘
- 여름휴가추천
- python
- 강원도캠핑
- 캠핑초보
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |