缩短dashboard名称 调整通知样式
This commit is contained in:
@@ -1,50 +1,115 @@
|
||||
<!-- src/components/common/Toast.vue:daisyUI toast 容器堆叠展示全部活动提示 -->
|
||||
<template>
|
||||
<div aria-live="polite" class="toast toast-top toast-end z-50 mt-16 gap-2">
|
||||
<div aria-live="polite" class="fixed right-4 top-4 z-50 flex flex-col gap-2 pt-14 sm:pt-4">
|
||||
<TransitionGroup name="toast">
|
||||
<div
|
||||
v-for="t in toasts"
|
||||
:key="t.id"
|
||||
role="status"
|
||||
class="alert shadow-lg"
|
||||
:class="{
|
||||
'alert-error': t.type === 'error',
|
||||
'alert-success': t.type === 'success',
|
||||
'alert-info': t.type === 'info',
|
||||
}"
|
||||
class="toast-item group flex items-start gap-2.5 rounded-lg border px-3.5 py-2.5 shadow-lg backdrop-blur-sm transition-colors"
|
||||
:class="typeClasses(t.type)"
|
||||
>
|
||||
<span class="min-w-0 flex-1 break-words">{{ t.message }}</span>
|
||||
<button type="button" class="btn btn-ghost btn-xs" aria-label="关闭提示" @click="dismiss(t.id)">✕</button>
|
||||
<component :is="iconForType(t.type)" class="mt-0.5 h-4 w-4 shrink-0" />
|
||||
<span class="min-w-0 flex-1 break-words text-sm leading-snug">{{ t.message }}</span>
|
||||
<button
|
||||
type="button"
|
||||
class="mt-0.5 -mr-0.5 shrink-0 rounded p-0.5 opacity-40 transition-opacity hover:opacity-100"
|
||||
aria-label="关闭"
|
||||
@click="dismiss(t.id)"
|
||||
>
|
||||
<XIcon class="h-3.5 w-3.5" />
|
||||
</button>
|
||||
<!-- progress bar -->
|
||||
<div
|
||||
v-if="t.duration > 0"
|
||||
class="absolute bottom-0 left-0 h-0.5 rounded-b-lg transition-all"
|
||||
:class="progressClass(t.type)"
|
||||
:style="{ width: '100%', animation: `shrink ${t.duration}ms linear forwards` }"
|
||||
/>
|
||||
</div>
|
||||
</TransitionGroup>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useToasts } from '@/composables/toast';
|
||||
import { useToasts, type ToastType } from '@/composables/toast';
|
||||
import { CheckCircleIcon, XCircleIcon, InfoIcon, XIcon } from '@lucide/vue';
|
||||
|
||||
const { toasts, dismiss } = useToasts();
|
||||
|
||||
const iconForType = (type: ToastType) => {
|
||||
switch (type) {
|
||||
case 'success': return CheckCircleIcon;
|
||||
case 'error': return XCircleIcon;
|
||||
default: return InfoIcon;
|
||||
}
|
||||
};
|
||||
|
||||
const typeClasses = (type: ToastType) => {
|
||||
switch (type) {
|
||||
case 'success':
|
||||
return 'border-success/20 bg-success/10 text-success-content dark:border-success/30 dark:bg-success/15';
|
||||
case 'error':
|
||||
return 'border-error/20 bg-error/10 text-error-content dark:border-error/30 dark:bg-error/15';
|
||||
default:
|
||||
return 'border-base-300 bg-base-100 text-base-content';
|
||||
}
|
||||
};
|
||||
|
||||
const progressClass = (type: ToastType) => {
|
||||
switch (type) {
|
||||
case 'success': return 'bg-success/60';
|
||||
case 'error': return 'bg-error/60';
|
||||
default: return 'bg-base-content/30';
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 只动 transform/opacity;系统开启减弱动态效果时由全局样式禁用 */
|
||||
.toast-enter-active,
|
||||
.toast-item {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
max-width: 22rem;
|
||||
}
|
||||
|
||||
/* Animations */
|
||||
.toast-enter-active {
|
||||
transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
}
|
||||
|
||||
.toast-leave-active {
|
||||
transition: opacity 0.25s ease, transform 0.25s ease;
|
||||
transition: all 0.2s ease-in;
|
||||
}
|
||||
|
||||
.toast-enter-from {
|
||||
opacity: 0;
|
||||
transform: translateY(-8px);
|
||||
transform: translateX(100%) scale(0.95);
|
||||
}
|
||||
|
||||
.toast-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateX(16px);
|
||||
transform: translateX(100%) scale(0.95);
|
||||
}
|
||||
|
||||
.toast-leave-active {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
.toast-move {
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
/* Progress bar shrink animation */
|
||||
@keyframes shrink {
|
||||
from { width: 100%; }
|
||||
to { width: 0%; }
|
||||
}
|
||||
|
||||
/* Respect reduced motion */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.toast-enter-active,
|
||||
.toast-leave-active,
|
||||
.toast-move {
|
||||
transition: opacity 0.15s ease !important;
|
||||
}
|
||||
.toast-enter-from,
|
||||
.toast-leave-to {
|
||||
transform: none !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
</span>
|
||||
</a>
|
||||
<RouterLink to="/dashboard" class="btn btn-primary btn-sm h-9 min-h-9 rounded-full px-3 sm:px-4 whitespace-nowrap">
|
||||
Open Dashboard
|
||||
Dashboard
|
||||
</RouterLink>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user