/** * Unified Toast System * * This module provides a comprehensive toast system that solves styling issues * and provides a single, flexible toast component for all use cases. * * Features: * - Proper background styling (no transparency issues) * - Loading states with spinners * - Progress bars for downloads/updates * - Success/error states * - Customizable icons and content * * Usage Examples: * * Simple loading toast: * ``` * import { showToast } from "./custom-toast"; * showToast({ * type: "loading", * title: "Loading...", * description: "Please wait..." * }); * ``` * * Download progress toast: * ``` * showToast({ * type: "download", * title: "Downloading Firefox 123.0", * progress: { percentage: 45, speed: "2.5", eta: "30s" } * }); * ``` * * Version update progress: * ``` * showToast({ * type: "version-update", * title: "Updating browser versions", * progress: { current: 3, total: 5, found: 12 } * }); * ``` */ import React from "react"; import { LuCheckCheck, LuDownload, LuRefreshCw, LuTriangleAlert, } from "react-icons/lu"; interface BaseToastProps { id?: string; title: string; description?: string; duration?: number; } interface LoadingToastProps extends BaseToastProps { type: "loading"; } interface SuccessToastProps extends BaseToastProps { type: "success"; } interface ErrorToastProps extends BaseToastProps { type: "error"; } interface DownloadToastProps extends BaseToastProps { type: "download"; stage?: | "downloading" | "extracting" | "verifying" | "completed" | "downloading (twilight rolling release)"; progress?: { percentage: number; speed?: string; eta?: string; }; } interface VersionUpdateToastProps extends BaseToastProps { type: "version-update"; progress?: { current: number; total: number; found: number; }; } interface FetchingToastProps extends BaseToastProps { type: "fetching"; browserName?: string; } interface TwilightUpdateToastProps extends BaseToastProps { type: "twilight-update"; browserName?: string; hasUpdate?: boolean; } type ToastProps = | LoadingToastProps | SuccessToastProps | ErrorToastProps | DownloadToastProps | VersionUpdateToastProps | FetchingToastProps | TwilightUpdateToastProps; function getToastIcon(type: ToastProps["type"], stage?: string) { switch (type) { case "success": return ; case "error": return ; case "download": if (stage === "completed") { return ( ); } return ; case "version-update": return ( ); case "fetching": return ( ); case "twilight-update": return ( ); default: return (
); } } export function UnifiedToast(props: ToastProps) { const { title, description, type } = props; const stage = "stage" in props ? props.stage : undefined; const progress = "progress" in props ? props.progress : undefined; return (
{getToastIcon(type, stage)}

{title}

{/* Download progress */} {type === "download" && progress && "percentage" in progress && stage === "downloading" && (

{progress.percentage.toFixed(1)}% {progress.speed && ` • ${progress.speed} MB/s`} {progress.eta && ` • ${progress.eta} remaining`}

)} {/* Version update progress */} {type === "version-update" && progress && "found" in progress && (

{progress.found} new versions found so far

{progress.current}/{progress.total}
)} {/* Twilight update progress */} {type === "twilight-update" && (

{"hasUpdate" in props && props.hasUpdate ? "New twilight build available for download" : "Checking for twilight updates..."}

{props.browserName && (

{props.browserName} • Rolling Release

)}
)} {/* Description */} {description && (

{description}

)} {/* Stage-specific descriptions for downloads */} {type === "download" && !description && ( <> {stage === "extracting" && (

Extracting browser files...

)} {stage === "verifying" && (

Verifying browser files...

)} {stage === "downloading (twilight rolling release)" && (

Downloading rolling release build...

)} )}
); }