diff --git a/apps/web/src/lib/stores/toasts.ts b/apps/web/src/lib/stores/toasts.ts new file mode 100644 index 0000000..0e8d06b --- /dev/null +++ b/apps/web/src/lib/stores/toasts.ts @@ -0,0 +1,41 @@ +import { writable } from 'svelte/store'; + +export type ToastType = 'info' | 'success' | 'error'; + +export type ToastItem = { + id: string; + type: ToastType; + message: string; + timeout?: number; +}; + +export const toasts = writable([]); + +function uid(): string { + return Math.random().toString(36).slice(2) + Date.now().toString(36); +} + +export function show(message: string, type: ToastType = 'info', timeout = 2500): string { + const id = uid(); + toasts.update((list) => [...list, { id, type, message, timeout }]); + if (timeout > 0) { + setTimeout(() => dismiss(id), timeout); + } + return id; +} + +export function success(message: string, timeout = 2500): string { + return show(message, 'success', timeout); +} + +export function error(message: string, timeout = 3500): string { + return show(message, 'error', timeout); +} + +export function info(message: string, timeout = 2500): string { + return show(message, 'info', timeout); +} + +export function dismiss(id: string): void { + toasts.update((list) => list.filter((t) => t.id !== id)); +} diff --git a/apps/web/src/lib/ui/data/FeedCard.svelte b/apps/web/src/lib/ui/data/FeedCard.svelte new file mode 100644 index 0000000..7d22c10 --- /dev/null +++ b/apps/web/src/lib/ui/data/FeedCard.svelte @@ -0,0 +1,73 @@ + + + +
+
+
{title}
+ {#if description}
{description}
{/if} + {#if url}
{url}
{/if} +
+
+ + +
+
+
+ + diff --git a/apps/web/src/lib/ui/feedback/EmptyState.svelte b/apps/web/src/lib/ui/feedback/EmptyState.svelte new file mode 100644 index 0000000..2a15e76 --- /dev/null +++ b/apps/web/src/lib/ui/feedback/EmptyState.svelte @@ -0,0 +1,13 @@ +
+ +
+ + diff --git a/apps/web/src/lib/ui/feedback/ErrorBanner.svelte b/apps/web/src/lib/ui/feedback/ErrorBanner.svelte new file mode 100644 index 0000000..af0cfa3 --- /dev/null +++ b/apps/web/src/lib/ui/feedback/ErrorBanner.svelte @@ -0,0 +1,16 @@ + + + diff --git a/apps/web/src/lib/ui/feedback/Toast.svelte b/apps/web/src/lib/ui/feedback/Toast.svelte new file mode 100644 index 0000000..c4c5c11 --- /dev/null +++ b/apps/web/src/lib/ui/feedback/Toast.svelte @@ -0,0 +1,59 @@ + + +
+ {#each $toasts as t (t.id)} +
+
{t.message}
+ +
+ {/each} +
+ + diff --git a/apps/web/src/lib/ui/layout/AppShell.svelte b/apps/web/src/lib/ui/layout/AppShell.svelte index a65fb21..baffe54 100644 --- a/apps/web/src/lib/ui/layout/AppShell.svelte +++ b/apps/web/src/lib/ui/layout/AppShell.svelte @@ -1,5 +1,6 @@
@@ -20,6 +21,8 @@ + +