mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-24 02:16:41 +02:00
refactor(shared-ui): centralize toast system across all web apps
- Add toast module to @manacore/shared-ui (toastStore, ToastContainer) - Remove local toast implementations from: - calendar/web - chat/web - clock/web - contacts/web - picture/web - storage/web - Update all apps to import toast from shared-ui - Consistent toast API: toast.success(), toast.error(), toast.info() Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
6d0d9d4f67
commit
14ce457c7b
56 changed files with 487 additions and 1249 deletions
|
|
@ -1,72 +0,0 @@
|
|||
<script lang="ts">
|
||||
import { toasts } from '$lib/stores/toast';
|
||||
import type { Toast } from '$lib/stores/toast';
|
||||
|
||||
function getIcon(type: Toast['type']) {
|
||||
switch (type) {
|
||||
case 'success':
|
||||
return '✓';
|
||||
case 'error':
|
||||
return '✕';
|
||||
case 'warning':
|
||||
return '⚠';
|
||||
case 'info':
|
||||
default:
|
||||
return 'ℹ';
|
||||
}
|
||||
}
|
||||
|
||||
function getColorClass(type: Toast['type']) {
|
||||
switch (type) {
|
||||
case 'success':
|
||||
return 'bg-green-500';
|
||||
case 'error':
|
||||
return 'bg-red-500';
|
||||
case 'warning':
|
||||
return 'bg-yellow-500';
|
||||
case 'info':
|
||||
default:
|
||||
return 'bg-blue-500';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="fixed bottom-4 right-4 z-50 flex flex-col gap-2">
|
||||
{#each $toasts as toast (toast.id)}
|
||||
<div
|
||||
class="flex items-center gap-3 rounded-lg bg-card px-4 py-3 shadow-lg border border-border animate-in slide-in-from-right duration-200"
|
||||
>
|
||||
<span
|
||||
class="{getColorClass(
|
||||
toast.type
|
||||
)} flex h-6 w-6 items-center justify-center rounded-full text-white text-sm"
|
||||
>
|
||||
{getIcon(toast.type)}
|
||||
</span>
|
||||
<span class="text-foreground">{toast.message}</span>
|
||||
<button
|
||||
onclick={() => toasts.remove(toast.id)}
|
||||
class="ml-2 text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
@keyframes slide-in-from-right {
|
||||
from {
|
||||
transform: translateX(100%);
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
transform: translateX(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.animate-in {
|
||||
animation: slide-in-from-right 0.2s ease-out;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
import { writable } from 'svelte/store';
|
||||
|
||||
export interface Toast {
|
||||
id: string;
|
||||
type: 'success' | 'error' | 'info' | 'warning';
|
||||
message: string;
|
||||
duration?: number;
|
||||
}
|
||||
|
||||
function createToastStore() {
|
||||
const { subscribe, update } = writable<Toast[]>([]);
|
||||
|
||||
function addToast(toast: Omit<Toast, 'id'>) {
|
||||
const id = crypto.randomUUID();
|
||||
const newToast = { ...toast, id };
|
||||
|
||||
update((toasts) => [...toasts, newToast]);
|
||||
|
||||
// Auto-remove after duration
|
||||
const duration = toast.duration || 5000;
|
||||
setTimeout(() => {
|
||||
removeToast(id);
|
||||
}, duration);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
function removeToast(id: string) {
|
||||
update((toasts) => toasts.filter((t) => t.id !== id));
|
||||
}
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
success: (message: string, duration?: number) =>
|
||||
addToast({ type: 'success', message, duration }),
|
||||
error: (message: string, duration?: number) => addToast({ type: 'error', message, duration }),
|
||||
info: (message: string, duration?: number) => addToast({ type: 'info', message, duration }),
|
||||
warning: (message: string, duration?: number) =>
|
||||
addToast({ type: 'warning', message, duration }),
|
||||
remove: removeToast,
|
||||
};
|
||||
}
|
||||
|
||||
export const toasts = createToastStore();
|
||||
|
||||
// Alias for compatibility with different import styles
|
||||
export const toast = toasts;
|
||||
|
|
@ -1,10 +1,9 @@
|
|||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { _ } from 'svelte-i18n';
|
||||
import { PageHeader } from '@manacore/shared-ui';
|
||||
import { PageHeader, toast } from '@manacore/shared-ui';
|
||||
import { alarmsStore } from '$lib/stores/alarms.svelte';
|
||||
import { authStore } from '$lib/stores/auth.svelte';
|
||||
import { toast } from '$lib/stores/toast';
|
||||
import type { CreateAlarmInput, Alarm } from '@clock/shared';
|
||||
import { ALARM_SOUNDS, DEFAULT_ALARM_PRESETS } from '@clock/shared';
|
||||
import { AlarmsSkeleton } from '$lib/components/skeletons';
|
||||
|
|
|
|||
|
|
@ -2,10 +2,9 @@
|
|||
import { onMount, onDestroy } from 'svelte';
|
||||
import { _ } from 'svelte-i18n';
|
||||
import { browser } from '$app/environment';
|
||||
import { PageHeader } from '@manacore/shared-ui';
|
||||
import { PageHeader, toast } from '@manacore/shared-ui';
|
||||
import { timersStore } from '$lib/stores/timers.svelte';
|
||||
import { authStore } from '$lib/stores/auth.svelte';
|
||||
import { toast } from '$lib/stores/toast';
|
||||
import { QUICK_TIMER_PRESETS, formatDuration } from '@clock/shared';
|
||||
import { TimersSkeleton } from '$lib/components/skeletons';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
<script lang="ts">
|
||||
import { onMount, onDestroy } from 'svelte';
|
||||
import { _ } from 'svelte-i18n';
|
||||
import { PageHeader } from '@manacore/shared-ui';
|
||||
import { PageHeader, toast } from '@manacore/shared-ui';
|
||||
import { worldClocksStore } from '$lib/stores/world-clocks.svelte';
|
||||
import { authStore } from '$lib/stores/auth.svelte';
|
||||
import { toast } from '$lib/stores/toast';
|
||||
import { POPULAR_TIMEZONES } from '@clock/shared';
|
||||
import WorldMap from '$lib/components/WorldMap.svelte';
|
||||
import { WorldClockSkeleton } from '$lib/components/skeletons';
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
import { theme } from '$lib/stores/theme.svelte';
|
||||
import { authStore } from '$lib/stores/auth.svelte';
|
||||
import { waitLocale } from '$lib/i18n';
|
||||
import ToastContainer from '$lib/components/ToastContainer.svelte';
|
||||
import { ToastContainer } from '@manacore/shared-ui';
|
||||
import { AppLoadingSkeleton } from '$lib/components/skeletons';
|
||||
|
||||
let { children } = $props();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue