Toast Notifications

Temporary, non-intrusive messages that provide feedback about user actions or system events.

Overview

Toast notifications are brief messages that appear temporarily at the edge of the screen to inform users about the success or failure of an action, without interrupting their workflow. They automatically disappear after a few seconds or can be manually dismissed.

Best Practices

Use toasts sparingly for important feedback. They should be brief, contextual, and actionable when necessary.

Toast Types

Different types of toasts for various message contexts and urgency levels.

HTML
<!-- Toast container (place at bottom of body) -->
<div id="toast-container" class="fixed top-4 right-4 space-y-2 z-50 pointer-events-none">
    <!-- Toasts will be injected here -->
</div>

<!-- Example trigger buttons -->
<button onclick="showToast('success', 'Task completed successfully!')">
    Show Success Toast
</button>

Duration & Persistence

Control toast visibility duration and persistence behavior.

JavaScript Implementation

JavaScript
// Toast notification system
function showToast(type, message, duration = 5000) {
    const container = document.getElementById("toast-container");
    if (!container) {
        console.error("Toast container not found");
        return;
    }

    const toast = createToastElement(type, message);
    container.appendChild(toast);

    // Animate in
    setTimeout(() => {
        toast.classList.add("animate-in");
    }, 10);

    // Auto-dismiss if duration > 0
    if (duration > 0) {
        setTimeout(() => {
            dismissToast(toast);
        }, duration);
    }
}

function createToastElement(type, message) {
    const toast = document.createElement("div");
    toast.className = `max-w-xs bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg pointer-events-auto transform translate-x-full opacity-0 transition-all duration-300`;
    toast.setAttribute("role", "alert");
    toast.setAttribute("tabindex", "-1");
    toast.style.minWidth = "300px";

    const icons = {
        success: '<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"></path>',
        error: '<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd"></path>',
        warning: '<path fill-rule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clip-rule="evenodd"></path>',
        info: '<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd"></path>'
    };

    const colors = {
        success: 'text-green-500',
        error: 'text-red-500',
        warning: 'text-yellow-500',
        info: 'text-blue-500'
    };

    toast.innerHTML = `
        <div class="flex p-4">
            <div class="flex-shrink-0">
                <svg class="h-5 w-5 ${colors[type] || colors.info}" fill="currentColor" viewBox="0 0 20 20">
                    ${icons[type] || icons.info}
                </svg>
            </div>
            <div class="ml-3 w-0 flex-1">
                <p class="text-sm font-medium text-gray-900 dark:text-white">
                    ${message}
                </p>
            </div>
            <div class="ml-4 flex-shrink-0 flex">
                <button type="button" class="inline-flex text-gray-400 hover:text-gray-500 dark:hover:text-gray-300 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500" onclick="dismissToast(this.closest('[role=alert]'))">
                    <span class="sr-only">Close</span>
                    <svg class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
                    </svg>
                </button>
            </div>
        </div>
    `;

    return toast;
}

function dismissToast(toast) {
    if (!toast) return;

    toast.style.transform = "translateX(100%)";
    toast.style.opacity = "0";

    setTimeout(() => {
        if (toast.parentNode) {
            toast.parentNode.removeChild(toast);
        }
    }, 300);
}

Usage Guidelines

Do's

  • Keep messages concise and actionable
  • Use appropriate semantic colors (green for success, red for errors)
  • Auto-dismiss success messages after 3-5 seconds
  • Make error messages persistent or longer duration

Don'ts

  • Don't use toasts for critical errors that require immediate action
  • Don't stack too many toasts simultaneously
  • Don't use toasts for complex messages or forms

Accessibility

  • Use role="alert" for error toasts and role="status" for info messages
  • Ensure toasts are announced by screen readers
  • Don't rely solely on color to convey message type