39 lines
1.0 KiB
Svelte
39 lines
1.0 KiB
Svelte
<script lang="ts">
|
||
import { dismissToast, toasts, type Toast } from '$lib/toast';
|
||
|
||
const toneLabel = (toast: Toast) => ({
|
||
success: 'OPERATION COMPLETE',
|
||
error: 'ACTION FAILED',
|
||
warning: 'ATTENTION REQUIRED',
|
||
info: 'SYSTEM UPDATE'
|
||
})[toast.tone];
|
||
|
||
function startTimer(_node: HTMLElement, toast: Toast) {
|
||
const timer = window.setTimeout(() => dismissToast(toast.id), toast.duration);
|
||
return {
|
||
destroy() {
|
||
window.clearTimeout(timer);
|
||
}
|
||
};
|
||
}
|
||
</script>
|
||
|
||
<aside class="toast-viewport" aria-label="Application feedback">
|
||
{#each $toasts as item (item.id)}
|
||
<article
|
||
class={`toast-message ${item.tone}`}
|
||
role={item.tone === 'error' || item.tone === 'warning' ? 'alert' : 'status'}
|
||
aria-atomic="true"
|
||
use:startTimer={item}
|
||
>
|
||
<i aria-hidden="true"></i>
|
||
<div>
|
||
<span>{toneLabel(item)}</span>
|
||
<strong>{item.title}</strong>
|
||
{#if item.message}<p>{item.message}</p>{/if}
|
||
</div>
|
||
<button type="button" aria-label={`Dismiss ${item.title}`} onclick={() => dismissToast(item.id)}>×</button>
|
||
</article>
|
||
{/each}
|
||
</aside>
|