diff --git a/src/lib/components/Snackbar.svelte b/src/lib/components/Snackbar.svelte
new file mode 100644
index 0000000..67a9cae
--- /dev/null
+++ b/src/lib/components/Snackbar.svelte
@@ -0,0 +1,31 @@
+
+
+{#if $snackbarStore?.message && $snackbarStore?.visible}
+
+ {$snackbarStore?.message}
+
+{/if}
+
+
diff --git a/src/lib/theme.ts b/src/lib/theme.ts
index 17457d6..5bfd88b 100644
--- a/src/lib/theme.ts
+++ b/src/lib/theme.ts
@@ -11,3 +11,16 @@ export const colors = {
dangerAccentColor: '#ddaeb2',
dangerActivecolor: '#b69092'
};
+
+export function colorAlpha(hex: string, alpha: number) {
+ const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
+
+ if (result) {
+ const { r, g, b } = {
+ r: parseInt(result[1], 16),
+ g: parseInt(result[2], 16),
+ b: parseInt(result[3], 16)
+ }
+ return `rgba(${r},${g},${b},${alpha})`
+ }
+}
\ No newline at end of file
diff --git a/src/lib/util/snackbar.ts b/src/lib/util/snackbar.ts
new file mode 100644
index 0000000..838b6c2
--- /dev/null
+++ b/src/lib/util/snackbar.ts
@@ -0,0 +1,18 @@
+import { writable } from "svelte/store";
+
+type Snackbar = {
+ visible: boolean;
+ message: string;
+};
+export const snackbarStore = writable(undefined);
+
+export function showSnackbar(message: string, duration = 3000) {
+ snackbarStore.set({
+ visible: true,
+ message
+ });
+
+ setTimeout(() => {
+ snackbarStore.set(undefined);
+ }, duration);
+}
\ No newline at end of file
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
index d11617d..2dab866 100644
--- a/src/routes/+layout.svelte
+++ b/src/routes/+layout.svelte
@@ -1,9 +1,11 @@
+