Skip to content

忍者按鈕 button

停用時會影分身的按鈕 ((-∀(-∀-)∀-))

技術關鍵字

名稱 描述
Pointer 事件偵測滑鼠或觸控點移動、點擊、懸停等等事件,取得座標、目標等等資訊
CSS 動畫基於 CSS transition 和 animation 實現

使用範例

基本用法

假的!都是假的!((((;゚Д゚)))

查看範例原始碼
vue
<template>
  <div class="w-full flex flex-col gap-4">
    <base-checkbox
      v-model="disabled"
      label="停用按鈕"
      class="border rounded p-4"
    />

    <div class="h-[50vh] flex items-center justify-center">
      <btn-ninja
        label="送出"
        :disabled
      />
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import BaseCheckbox from '../../base-checkbox.vue'
import BtnNinja from '../btn-ninja.vue'

const disabled = ref(false)
</script>

謹慎的確認

消滅所有影分身後,才能點擊「確認」。( •̀ ω •́ )✧

請確認您的操作! 你即將啟動「自動刪除所有週一早上的會議」功能。此操作將會:
  • 永久刪除日曆中所有週一早上的會議
  • 取消所有相關的會議室預約
  • 自動發送「我討厭星期一」的郵件給所有與會者
取消
🎉 操作已完成!
查看範例原始碼
vue
<template>
  <div class="relative flex flex-col gap-3 border border-red-300 rounded-lg bg-red-50 p-6">
    <span class="text-xl text-red-800 font-bold">
      請確認您的操作!
    </span>

    <span class="mt-2 text-red-700">
      你即將啟動「自動刪除所有週一早上的會議」功能。此操作將會:
    </span>

    <ul class="list-disc list-inside text-sm text-red-600 !m-0">
      <li>永久刪除日曆中所有週一早上的會議</li>
      <li>取消所有相關的會議室預約</li>
      <li>自動發送「我討厭星期一」的郵件給所有與會者</li>
    </ul>

    <div class="flex justify-end gap-4">
      <btn-ninja>
        <div class="cursor-pointer p-2 px-4 text-gray-800">
          取消
        </div>
      </btn-ninja>

      <btn-ninja
        v-slot="{ isHidden }"
        :disabled
        @show="disabled = false"
      >
        <base-btn
          label="確認"
          class="active:scale-95 !border-red-600"
          :class="{
            'text-red-600 !border-dashed': disabled || isHidden,
            '!bg-red-600 !text-white': !disabled,
          }"
          @click="handleClick"
        />
      </btn-ninja>
    </div>

    <div
      class="pointer-events-none absolute inset-0 flex items-center justify-center bg-black/90 duration-500"
      :class="done ? ' opacity-100' : 'opacity-0'"
    >
      <span class="text-2xl text-white font-bold">
        🎉 操作已完成!
      </span>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import BaseBtn from '../../base-btn.vue'
import BtnNinja from '../btn-ninja.vue'

const disabled = ref(true)

const done = ref(false)
function handleClick() {
  if (disabled.value) {
    return
  }

  done.value = true
  setTimeout(() => {
    done.value = false
    disabled.value = true
  }, 2000)
}
</script>

原理

對 Vue 有一定經驗的人,應該都知道 Vue 元件中可以透過 slot 提供使用者插入自定義 template 內容。

忽然某天腦中冒出一個想法:如果同一個 slot 重複使用會怎麼樣?ヾ(◍'౪`◍)ノ゙

於是這個元件就這樣誕生啦。ᕕ( ゚ ∀。)ᕗ

原始碼

API

Props

interface Props {
  label?: string;
  /** 分身數量 */
  count?: number;
  disabled?: boolean;
}

Emits

interface Emits {
  click: [];
  hidden: [];
  show: [];
}

Slots

interface Slots {
  default?: (props: { isHidden: boolean }) => unknown;
}

v0.41.0