Complete Toaster system
This commit is contained in:
60
src/lib/ToastSystem/Toast.svelte
Normal file
60
src/lib/ToastSystem/Toast.svelte
Normal file
@@ -0,0 +1,60 @@
|
||||
<script lang="ts">
|
||||
import {
|
||||
melt,
|
||||
type Toast,
|
||||
type ToastsElements,
|
||||
} from '@melt-ui/svelte';
|
||||
import type { ToastData } from "$lib/ToastSystem/types";
|
||||
import { onMount } from "svelte";
|
||||
|
||||
interface Props {
|
||||
elements: ToastsElements,
|
||||
toast: Toast<ToastData>,
|
||||
}
|
||||
|
||||
const { elements, toast }: Props = $props();
|
||||
const { content, title, description, close } = $derived(elements);
|
||||
const { data, id, getPercentage } = $derived(toast);
|
||||
|
||||
const alertClass = $derived.by(() => {
|
||||
switch (data.type) {
|
||||
case "success":
|
||||
return 'alert-success';
|
||||
case "warning":
|
||||
return 'alert-warning';
|
||||
case "error":
|
||||
return 'alert-error';
|
||||
case "info":
|
||||
return 'alert-info';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
});
|
||||
|
||||
let percentage = $state(0);
|
||||
|
||||
onMount(() => {
|
||||
let frame: number;
|
||||
const updatePercentage = () => {
|
||||
percentage = getPercentage();
|
||||
frame = requestAnimationFrame(updatePercentage);
|
||||
};
|
||||
frame = requestAnimationFrame(updatePercentage);
|
||||
return () => cancelAnimationFrame(frame);
|
||||
});
|
||||
</script>
|
||||
|
||||
<div use:melt={$content(id)} class="relative w-[70%] visible">
|
||||
<div class="absolute w-full flex flex-col px-2">
|
||||
<progress class="progress h-1 w-full" value={percentage} max="100"></progress>
|
||||
</div>
|
||||
<div class={["alert", alertClass]}>
|
||||
<button use:melt={$close(id)} aria-label="close notification" class="absolute right-2 top-0">x</button>
|
||||
<h3 use:melt={$title(id)} class="font-bold">
|
||||
{data.title}
|
||||
</h3>
|
||||
<div use:melt={$description(id)}>
|
||||
{data.description}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
23
src/lib/ToastSystem/Toaster.svelte
Normal file
23
src/lib/ToastSystem/Toaster.svelte
Normal file
@@ -0,0 +1,23 @@
|
||||
<script lang="ts" module>
|
||||
import { createToaster } from '@melt-ui/svelte';
|
||||
import type { ToastData } from "$lib/ToastSystem/types";
|
||||
|
||||
const {
|
||||
elements,
|
||||
helpers,
|
||||
states: { toasts },
|
||||
actions: { portal }
|
||||
} = createToaster<ToastData>();
|
||||
|
||||
export const addToast = helpers.addToast;
|
||||
</script>
|
||||
<script>
|
||||
import Toast from "$lib/ToastSystem/Toast.svelte";
|
||||
</script>
|
||||
|
||||
<div use:portal
|
||||
class="fixed w-screen h-screen top-0 z-50 pb-4 flex flex-col-reverse justify-start items-center gap-2 invisible">
|
||||
{#each $toasts as toast (toast.id)}
|
||||
<Toast {elements} {toast}/>
|
||||
{/each}
|
||||
</div>
|
||||
5
src/lib/ToastSystem/types.ts
Normal file
5
src/lib/ToastSystem/types.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export type ToastData = {
|
||||
title: string
|
||||
description: string
|
||||
type: 'info' | 'success' | 'warning' | 'error',
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
<script lang="ts" module>
|
||||
import { createToaster, melt } from '@melt-ui/svelte';
|
||||
|
||||
export type ToastData = {
|
||||
title: string
|
||||
description: string
|
||||
color: string
|
||||
}
|
||||
// TODO: Change color with type e setta classe
|
||||
|
||||
// TODO: Usa getPercentage per mostrare la loading bar sugli alert!
|
||||
|
||||
const {
|
||||
elements: { content, title, description, close },
|
||||
helpers,
|
||||
states: { toasts },
|
||||
actions: { portal }
|
||||
} = createToaster<ToastData>();
|
||||
|
||||
export const addToast = helpers.addToast;
|
||||
</script>
|
||||
|
||||
<div use:portal class="fixed w-screen top-0 z-50 m-4 flex flex-col items-center gap-2 invisible">
|
||||
{#each $toasts as { id, data } (id)}
|
||||
<div use:melt={$content(id)} class="alert alert-info relative w-[70%] visible">
|
||||
<div>
|
||||
<h3 use:melt={$title(id)} class="font-bold">
|
||||
{data.title}
|
||||
<!-- <span style:color={data.color}></span>-->
|
||||
</h3>
|
||||
<div use:melt={$description(id)}>
|
||||
{data.description}
|
||||
</div>
|
||||
</div>
|
||||
<button use:melt={$close(id)} aria-label="close notification" class="absolute right-2 top-0">x</button>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import '../app.css';
|
||||
import Toaster from "$lib/Toaster.svelte";
|
||||
import Toaster from "$lib/ToastSystem/Toaster.svelte";
|
||||
|
||||
let { children } = $props();
|
||||
</script>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { scale } from 'svelte/transition';
|
||||
import { goto } from "$app/navigation";
|
||||
import BSlideOverlay from "$lib/BSlideOverlay.svelte";
|
||||
import { addToast } from '$lib/Toaster.svelte';
|
||||
import { addToast } from '$lib/ToastSystem/Toaster.svelte';
|
||||
|
||||
let { data } = $props();
|
||||
|
||||
@@ -29,11 +29,11 @@
|
||||
|
||||
function test() {
|
||||
addToast({
|
||||
closeDelay: 50000,
|
||||
closeDelay: 5000,
|
||||
data: {
|
||||
title: 'Success',
|
||||
description: 'The resource was created!',
|
||||
color: 'green'
|
||||
type: 'success'
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user