| <script> |
| import { toasts } from '$stores/notifications.js'; |
| import { fly, fade } from 'svelte/transition'; |
|
|
| let items = []; |
| toasts.subscribe((v) => (items = v)); |
|
|
| const icons = { |
| success: 'M5 13l4 4L19 7', |
| error: 'M6 18L18 6M6 6l12 12', |
| warning: 'M12 9v2m0 4h.01M12 2a10 10 0 100 20 10 10 0 000-20z', |
| info: 'M13 16h-1v-4h-1m1-4h.01M12 2a10 10 0 100 20 10 10 0 000-20z' |
| }; |
|
|
| const colors = { |
| success: 'bg-pos-success', |
| error: 'bg-pos-danger', |
| warning: 'bg-pos-warning text-gray-900', |
| info: 'bg-pos-info' |
| }; |
| </script> |
|
|
| <div class="fixed top-4 right-4 z-[100] flex flex-col gap-2 max-w-sm"> |
| {#each items as toast (toast.id)} |
| <div |
| class="flex items-center gap-3 px-4 py-3 rounded-lg shadow-xl {colors[toast.type]} text-sm font-medium" |
| in:fly={{ x: 300, duration: 300 }} |
| out:fade={{ duration: 200 }} |
| > |
| <svg class="w-5 h-5 flex-shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"> |
| <path stroke-linecap="round" stroke-linejoin="round" d={icons[toast.type]} /> |
| </svg> |
| <span class="flex-1">{toast.message}</span> |
| <button |
| class="opacity-70 hover:opacity-100 transition-opacity" |
| onclick={() => toasts.remove(toast.id)} |
| > |
| <svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"> |
| <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" /> |
| </svg> |
| </button> |
| </div> |
| {/each} |
| </div> |
| |