diff --git a/src/comp/toast/toast.svelte b/src/comp/toast/toast.svelte
new file mode 100644
index 0000000..e4fed1e
--- /dev/null
+++ b/src/comp/toast/toast.svelte
@@ -0,0 +1,198 @@
+
+
+
+
+
diff --git a/src/comp/toast/toastmanager.svelte b/src/comp/toast/toastmanager.svelte
new file mode 100644
index 0000000..eb46251
--- /dev/null
+++ b/src/comp/toast/toastmanager.svelte
@@ -0,0 +1,34 @@
+
+
+
+
+
{expand = true;}} on:mouseleave={() => {expand = false;}}>
+ {#each $toasts as toast (toast.id)}
+
+ {/each}
+
diff --git a/src/lib/memory/toast.js b/src/lib/memory/toast.js
new file mode 100644
index 0000000..72b189b
--- /dev/null
+++ b/src/lib/memory/toast.js
@@ -0,0 +1,82 @@
+import { hashOf } from "$lib/client/hash";
+import { writable } from "svelte/store";
+
+/**
+ * @typedef {'error'} ToastType
+ * @typedef {number} ToastID
+ * @typedef {{
+ * type: ToastType,
+ * title: string,
+ * message: string,
+ * dismissCallback?: function(): void,
+ * timeout?: number | null
+ * }} Toast
+ */
+
+/**
+ * @type {import("svelte/store").Writable<(Toast & {id: ToastID})[]>}
+ */
+const toasts = writable([]);
+
+export default toasts;
+
+/**
+ * @param {Toast} toast
+ * @returns {ToastID}
+ */
+export function addToastObject(toast) {
+ /** @type {Toast & {id: ToastID}} */
+ const entry = {
+ id: hashOf(Date.now()),
+ ...toast,
+ }
+
+ toasts.update((list) => {return [...list, entry];});
+
+ if (entry.timeout) {
+ setTimeout(() => {removeToast(entry.id);}, entry.timeout);
+ }
+
+ return entry.id;
+}
+
+/**
+ * @param {ToastType} type
+ * @param {string} title
+ * @param {string} message
+ * @param {function(): void} dismissCallback
+ * @param {number | undefined} [timeout=10000]
+ * @returns {ToastID}
+ */
+export function addToastCallback(type, title, message, dismissCallback, timeout = 10000) {
+ return addToastObject({
+ type: type,
+ title: title,
+ message: message,
+ dismissCallback: dismissCallback,
+ timeout: timeout,
+ });
+}
+
+/**
+ * @param {ToastType} type
+ * @param {string} title
+ * @param {string} message
+ * @param {number | undefined | null} [timeout=10000]
+ * @returns {ToastID}
+ */
+export function addToast(type, title, message, timeout = 10000) {
+ return addToastObject({
+ type: type,
+ title: title,
+ message: message,
+ timeout: timeout,
+ });
+}
+
+/**
+ * @param {number} id
+ */
+export function removeToast(id) {
+ toasts.update((list) => {return list.filter(x => x.id != id);});
+}
diff --git a/src/routes/(app)/compose/+page.svelte b/src/routes/(app)/compose/+page.svelte
index 70747e4..5eb0cc7 100644
--- a/src/routes/(app)/compose/+page.svelte
+++ b/src/routes/(app)/compose/+page.svelte
@@ -9,13 +9,6 @@
* }}
*/
export let data;
-
- $: {
- if ($page.form) {
- console.log($page.form);
- addToast('error', 'Test', 'cool!', null);
- }
- };