File size: 1,876 Bytes
395e9dc
 
 
 
 
 
 
1f4cfcb
395e9dc
 
 
1f4cfcb
 
 
 
395e9dc
 
 
 
 
 
 
 
 
 
 
 
1f4cfcb
395e9dc
 
 
 
 
1f4cfcb
 
 
 
 
395e9dc
 
 
1f4cfcb
 
 
 
 
395e9dc
 
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<!--
  ToastHost — toast 容器,挂在 App 顶层
-->
<template>
  <div class="fixed top-3 right-3 z-[100] space-y-2 max-w-sm pointer-events-none">
    <transition-group tag="div" class="space-y-2">
      <div v-for="t in state.items" :key="t.id"
        class="pointer-events-auto rounded-lg border bg-surface shadow-card px-4 py-3 flex items-start gap-3"
        :class="[toneClass(t.tone), t.leaving ? 'animate-toast-out' : 'animate-toast-in']"
        @click="dismiss(t.id)">
        <span class="shrink-0 mt-0.5">
          <Check v-if="t.tone === 'success'" class="w-4 h-4 text-emerald-700" :stroke-width="2" />
          <X v-else-if="t.tone === 'error'" class="w-4 h-4 text-rose-700" :stroke-width="2" />
          <TriangleAlert v-else-if="t.tone === 'warning'" class="w-4 h-4 text-amber-700" :stroke-width="2" />
          <Info v-else class="w-4 h-4 text-sky-700" :stroke-width="2" />
        </span>
        <div class="flex-1 min-w-0">
          <div class="text-sm font-semibold leading-tight" :class="titleColor(t.tone)">{{ t.text }}</div>
          <div v-if="t.detail" class="text-xs mt-1 opacity-70 break-all" :class="titleColor(t.tone)">{{ t.detail }}</div>
        </div>
      </div>
    </transition-group>
  </div>
</template>

<script setup>
import { useToast } from '../composables/useToast.js'
import { Check, Info, TriangleAlert, X } from 'lucide-vue-next'

const { state, dismiss } = useToast()

function toneClass(tone) {
  return {
    success: 'bg-emerald-50 border-emerald-200',
    error: 'bg-rose-50 border-rose-200',
    warning: 'bg-amber-50 border-amber-200',
    info: 'bg-sky-50 border-sky-200',
  }[tone] || 'bg-sky-50 border-sky-200'
}
function titleColor(tone) {
  return {
    success: 'text-emerald-900',
    error: 'text-rose-900',
    warning: 'text-amber-900',
    info: 'text-sky-900',
  }[tone] || 'text-sky-900'
}
</script>