Icon Toggle 可簡單設定 true
與 false
,但必須搭配 JavaScript 維護 State 並動態改變 Utility。
Version
Vue 3.0.5
Tailwind CSS 2.1.1
Icon Toggle
功能與 Simple Toggle 一樣,但帶有 SVG Icon。
<template>
<button @click="onClick" type="button" :class="isOn ? 'bg-indigo-600' : 'bg-gray-200'" class="relative inline-flex 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:ring-2 focus:ring-offset-2 focus:ring-indigo-500" aria-pressed="false">
<span class="sr-only">Use setting</span>
<span :class="isOn ? 'translate-x-5' : 'translate-x-0'" class="pointer-events-none relative inline-block h-5 w-5 rounded-full bg-white shadow transform ring-0 transition ease-in-out duration-200">
<span :class="isOn ? 'opacity-0 ease-out duration-100' : 'opacity-100 ease-in duration-200'" class="absolute inset-0 h-full w-full flex items-center justify-center transition-opacity" aria-hidden="true">
<svg class="bg-white h-3 w-3 text-gray-400" fill="none" viewBox="0 0 12 12">
<path d="M4 8l2-2m0 0l2-2M6 6L4 4m2 2l2 2" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</span>
<span :class="isOn ? 'opacity-100 ease-in duration-200' : 'opacity-0 ease-out duration-100'" class="absolute inset-0 h-full w-full flex items-center justify-center transition-opacity" aria-hidden="true">
<svg class="bg-white h-3 w-3 text-indigo-600" fill="currentColor" viewBox="0 0 12 12">
<path d="M3.707 5.293a1 1 0 00-1.414 1.414l1.414-1.414zM5 8l-.707.707a1 1 0 001.414 0L5 8zm4.707-3.293a1 1 0 00-1.414-1.414l1.414 1.414zm-7.414 2l2 2 1.414-1.414-2-2-1.414 1.414zm3.414 2l4-4-1.414-1.414-4 4 1.414 1.414z"/>
</svg>
</span>
</span>
</button>
</template>
<script setup>
ref: isOn = true
let onClick = () => isOn = !isOn
</script>
第 2 行
<button @click="onClick" :class="isOn ? 'bg-indigo-600' : 'bg-gray-200'">
外層
<button>
需攔截click
event 維護 state當
isOn
為true
時使用bg-indigo-600
,否則使用bg-gray-200
第 4 行
<span :class="isOn ? 'translate-x-5' : 'translate-x-0'">
當 isOn
為 true
時使用 translate-x-5
,否則使用 translate-x-0
。
第 5 行
<span :class="isOn ? 'opacity-0 ease-out duration-100' : 'opacity-100 ease-in duration-200'">
當 isOn
為 true
時顯示打叉 icon,否則隱藏 icon。
10 行
<span :class="isOn ? 'opacity-100 ease-in duration-200' : 'opacity-0 ease-out duration-100'">
當 isOn
為 true
時顯示打勾 icon,否則隱藏 icon。
20 行
ref: isOn = true
定義 isOn
state 並設定初始值為 true
。
22 行
let onClick = () => isOn = !isOn
onClick()
會對 isOn
state 做 toggle。
Function Pipeline
<template>
<button @click="onClick" type="button" :class="isOn ? 'bg-indigo-600' : 'bg-gray-200'" class="relative inline-flex 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:ring-2 focus:ring-offset-2 focus:ring-indigo-500" aria-pressed="false">
<span class="sr-only">Use setting</span>
<span :class="isOn ? 'translate-x-5' : 'translate-x-0'" class="pointer-events-none relative inline-block h-5 w-5 rounded-full bg-white shadow transform ring-0 transition ease-in-out duration-200">
<span :class="isOn ? 'opacity-0 ease-out duration-100' : 'opacity-100 ease-in duration-200'" class="absolute inset-0 h-full w-full flex items-center justify-center transition-opacity" aria-hidden="true">
<svg class="bg-white h-3 w-3 text-gray-400" fill="none" viewBox="0 0 12 12">
<path d="M4 8l2-2m0 0l2-2M6 6L4 4m2 2l2 2" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</span>
<span :class="isOn ? 'opacity-100 ease-in duration-200' : 'opacity-0 ease-out duration-100'" class="absolute inset-0 h-full w-full flex items-center justify-center transition-opacity" aria-hidden="true">
<svg class="bg-white h-3 w-3 text-indigo-600" fill="currentColor" viewBox="0 0 12 12">
<path d="M3.707 5.293a1 1 0 00-1.414 1.414l1.414-1.414zM5 8l-.707.707a1 1 0 001.414 0L5 8zm4.707-3.293a1 1 0 00-1.414-1.414l1.414 1.414zm-7.414 2l2 2 1.414-1.414-2-2-1.414 1.414zm3.414 2l4-4-1.414-1.414-4 4 1.414 1.414z"/>
</svg>
</span>
</span>
</button>
</template>
<script setup>
import { ref } from 'vue'
import { pipe, not } from 'ramda'
import { read, write } from 'vue3-fp'
let isOn = ref(true)
let onClick = pipe(
read(isOn),
not,
write(isOn)
)
</script>
26 行
let onClick = pipe(
read(isOn),
not,
write(isOn)
)
read(isOn)
:讀取isOn
statenot()
:對isOn
state 做 togglewrite(isOn)
:寫入isOn
state
Conclusion
- Icon Toggle 必須自行攔截
click
event 並對isOn
state 做 toggle - Tailwind UI 常有兩個 utility 根據 state 改變而切換 utility,可簡單在
:class
內使用?:
operator