39 lines
1.7 KiB
Vue
39 lines
1.7 KiB
Vue
<script setup lang="ts">
|
|
import { ToastClose, ToastProvider, ToastRoot, ToastTitle, ToastViewport } from 'reka-ui';
|
|
import { useToast, type ToastSeverity } from '@/composables/useToast';
|
|
import { useTranslations } from '@/composables/useVanguard';
|
|
|
|
const { messages, remove } = useToast();
|
|
const { __ } = useTranslations();
|
|
|
|
const styles: Record<ToastSeverity, { container: string; icon: string }> = {
|
|
success: { container: 'border-green-200 bg-green-50 text-green-800', icon: 'fas fa-check-circle' },
|
|
info: { container: 'border-sky-200 bg-sky-50 text-sky-800', icon: 'fas fa-info-circle' },
|
|
warn: { container: 'border-amber-200 bg-amber-50 text-amber-800', icon: 'fas fa-exclamation-triangle' },
|
|
error: { container: 'border-red-200 bg-red-50 text-red-800', icon: 'fas fa-times-circle' },
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<ToastProvider>
|
|
<ToastRoot
|
|
v-for="message in messages"
|
|
:key="message.id"
|
|
:duration="message.life"
|
|
class="flex items-start gap-2 rounded-md border px-4 py-3 shadow-md data-[state=closed]:opacity-0"
|
|
:class="styles[message.severity].container"
|
|
@update:open="(open: boolean) => !open && remove(message.id)"
|
|
>
|
|
<i :class="styles[message.severity].icon" class="mt-1 shrink-0" aria-hidden="true" />
|
|
|
|
<ToastTitle class="flex-1">{{ message.summary }}</ToastTitle>
|
|
|
|
<ToastClose class="cursor-pointer opacity-60 hover:opacity-100" :aria-label="__('Close')">
|
|
<i class="fas fa-times" aria-hidden="true" />
|
|
</ToastClose>
|
|
</ToastRoot>
|
|
|
|
<ToastViewport class="fixed top-4 left-1/2 -translate-x-1/2 z-100 flex w-96 max-w-[calc(100vw-2rem)] flex-col gap-2" />
|
|
</ToastProvider>
|
|
</template>
|