// Toast Component // Notification toast with auto-dismiss and animations import { Theme, Typography, SpacingSystem } from "../theme/theme.slint"; import { Animations } from "../utils/animations.slint"; // Toast message structure export struct ToastMessage { message: string, variant: string, // default | success | error | warning show: bool, } // Single toast item export component Toast { // Public properties in property message: ""; in property variant: "default"; // default | success | error | warning in-out property show: false; // Callbacks callback dismissed(); // Calculate colors based on variant private property bg-color: { if variant == "success" { #10b981 } else if variant == "error" { Theme.colors.destructive } else if variant == "warning" { #f59e0b } else { Theme.colors.card } }; private property text-color: { if variant == "success" { #ffffff } else if variant == "error" { Theme.colors.destructive-foreground } else if variant == "warning" { #ffffff } else { Theme.colors.card-foreground } }; private property icon: { if variant == "success" { "✓" } else if variant == "error" { "✕" } else if variant == "warning" { "⚠" } else { "ℹ" } }; // Animation properties property translate-y: show ? 0px : -20px; property opacity-val: show ? 1.0 : 0.0; animate translate-y, opacity-val { duration: Animations.durations.normal; easing: Animations.ease-out; } width: 350px; height: show ? 60px : 0px; if show: Rectangle { y: translate-y; opacity: opacity-val; background: bg-color; border-radius: SpacingSystem.radius.lg; border-width: 1px; border-color: Theme.colors.border; drop-shadow-blur: 10px; drop-shadow-color: #00000020; drop-shadow-offset-y: 4px; HorizontalLayout { padding: SpacingSystem.spacing.s4; spacing: SpacingSystem.spacing.s3; alignment: space-between; HorizontalLayout { spacing: SpacingSystem.spacing.s3; // Icon Text { text: icon; font-size: Typography.sizes.xl; color: text-color; vertical-alignment: center; } // Message Text { text: message; font-size: Typography.sizes.base; color: text-color; vertical-alignment: center; wrap: word-wrap; } } // Close button Rectangle { width: 24px; height: 24px; border-radius: SpacingSystem.radius.sm; background: close-touch.has-hover ? #00000020 : Colors.transparent; animate background { duration: Animations.durations.fast; easing: Animations.ease-in-out; } Text { text: "✕"; font-size: Typography.sizes.sm; color: text-color; horizontal-alignment: center; vertical-alignment: center; } close-touch := TouchArea { clicked => { root.dismissed(); } } } } } } // Toast container (manages multiple toasts) export component ToastContainer { in property <[ToastMessage]> toasts: []; callback toast-dismissed(int); // Position at top-right corner width: 370px; VerticalLayout { spacing: SpacingSystem.spacing.s2; alignment: start; for toast[index] in toasts: Toast { message: toast.message; variant: toast.variant; show: toast.show; dismissed => { root.toast-dismissed(index); } } } }