diff --git a/src/CloseIcon.svelte b/src/CloseIcon.svelte
new file mode 100644
index 0000000..6423df4
--- /dev/null
+++ b/src/CloseIcon.svelte
@@ -0,0 +1,18 @@
+
+
+
diff --git a/src/ErrorIcon.svelte b/src/ErrorIcon.svelte
new file mode 100644
index 0000000..60b814a
--- /dev/null
+++ b/src/ErrorIcon.svelte
@@ -0,0 +1,19 @@
+
+
+
diff --git a/src/InfoIcon.svelte b/src/InfoIcon.svelte
new file mode 100644
index 0000000..4f4908d
--- /dev/null
+++ b/src/InfoIcon.svelte
@@ -0,0 +1,18 @@
+
+
+
diff --git a/src/SuccessIcon.svelte b/src/SuccessIcon.svelte
new file mode 100644
index 0000000..4998608
--- /dev/null
+++ b/src/SuccessIcon.svelte
@@ -0,0 +1,18 @@
+
+
+
diff --git a/src/Toast.svelte b/src/Toast.svelte
new file mode 100644
index 0000000..89a335e
--- /dev/null
+++ b/src/Toast.svelte
@@ -0,0 +1,66 @@
+
+
+
+ {#if type === "success"}
+
+ {:else if type === "error"}
+
+ {:else}
+
+ {/if}
+
+
+
+
+
+ {#if dismissible}
+
+ {/if}
+
+
+
diff --git a/src/Toasts.svelte b/src/Toasts.svelte
new file mode 100644
index 0000000..379c894
--- /dev/null
+++ b/src/Toasts.svelte
@@ -0,0 +1,32 @@
+
+
+{#if $toasts}
+
+ {#each $toasts as toast (toast.id)}
+ dismissToast(toast.id)}>{toast.message}
+ {/each}
+
+{/if}
+
+
diff --git a/src/lib/toast.ts b/src/lib/toast.ts
new file mode 100644
index 0000000..eb3e3ec
--- /dev/null
+++ b/src/lib/toast.ts
@@ -0,0 +1,10 @@
+class Toast {
+ constructor(text: String, type: String, dismissable: boolean, timeout: number ) {
+ id = text
+ }
+
+ id: String;
+ type: String;
+ dismissible: boolean;
+ timeout: number;
+}
\ No newline at end of file
diff --git a/src/main.svelte b/src/main.svelte
index 97f8566..60a2c85 100644
--- a/src/main.svelte
+++ b/src/main.svelte
@@ -1,5 +1,6 @@
@@ -51,7 +52,5 @@
-
-
-
\ No newline at end of file
+
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
index c60d686..fe5442d 100644
--- a/src/routes/+page.svelte
+++ b/src/routes/+page.svelte
@@ -1,5 +1,7 @@
-
\ No newline at end of file
+
+
\ No newline at end of file
diff --git a/src/snackbar.svelte b/src/snackbar.svelte
new file mode 100644
index 0000000..a68d23a
--- /dev/null
+++ b/src/snackbar.svelte
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+ {#each messages as message}
+
{message}
+ {/each}
+
\ No newline at end of file
diff --git a/src/store.ts b/src/store.ts
new file mode 100644
index 0000000..6a32ca9
--- /dev/null
+++ b/src/store.ts
@@ -0,0 +1,27 @@
+import { writable } from "svelte/store";
+
+export const toasts = writable([]);
+
+export const addToast = (toast: ) => {
+ // Create a unique ID so we can easily find/remove it
+ // if it is dismissible/has a timeout.
+ const id = Math.floor(Math.random() * 10000);
+
+ // Setup some sensible defaults for a toast.
+ const defaults = {
+ id,
+ type: "info",
+ dismissible: true,
+ timeout: 3000,
+ };
+
+ // Push the toast to the top of the list of toasts
+ toasts.update((all) => [{ ...defaults, ...toast }, ...all]);
+
+ // If toast is dismissible, dismiss it after "timeout" amount of time.
+ if (toast.timeout) setTimeout(() => dismissToast(id), toast.timeout);
+};
+
+export const dismissToast = (id) => {
+ toasts.update((all) => all.filter((t) => t.id !== id));
+};