UIBuilder button

showOverlay function:

/** Creates and displays an overlay window with customizable content and behavior
 * @param {object} options - Configuration options for the overlay
 *   @param {string} options.content - Main content (text or HTML) to display
 *   @param {string} [options.title] - Optional title above the main content
 *   @param {string} [options.icon] - Optional icon to display left of title (HTML or text)
 *   @param {string} [options.type] - Overlay type: 'success', 'info', 'warning', or 'error'
 *   @param {boolean} [options.showDismiss] - Whether to show dismiss button (auto-determined if not set)
 *   @param {number|null} [options.autoClose] - Auto-close delay in seconds (null for no auto-close)
 *   @param {boolean} [options.time] - Show timestamp in overlay (default: true)
 * @returns {object} Object with close() method to manually close the overlay
 */
function showOverlay(options = {}) {
    const {
        content = '',
        title = '',
        icon = '',
        type = 'info',
        showDismiss,
        autoClose = 5,
        time = true,
    } = options

    const overlayContainerId = 'uib-info-overlay'

    // Get or create the main overlay container
    let overlayContainer = document.getElementById(overlayContainerId)
    if (!overlayContainer) {
        overlayContainer = document.createElement('div')
        overlayContainer.id = overlayContainerId
        document.body.appendChild(overlayContainer)
    }

    // Generate unique ID for this overlay entry
    const entryId = `overlay-entry-${Date.now()}-${Math.random().toString(36)
        .substr(2, 9)}`

    // Create individual overlay entry
    const overlayEntry = document.createElement('div')
    overlayEntry.id = entryId
    overlayEntry.style.marginBottom = '0.5rem'

    // Define type-specific styles
    const typeStyles = {
        info: {
            iconDefault: 'ℹ️',
            titleDefault: 'Information',
            color: 'hsl(188.2deg 77.78% 40.59%)',
        },
        success: {
            iconDefault: '✅',
            titleDefault: 'Success',
            color: 'hsl(133.7deg 61.35% 40.59%)',
        },
        warning: {
            iconDefault: '⚠️',
            titleDefault: 'Warning',
            color: 'hsl(35.19deg 84.38% 62.35%)',
        },
        error: {
            iconDefault: '❌',
            titleDefault: 'Error',
            color: 'hsl(2.74deg 92.59% 62.94%)',
        },
    }

    const currentTypeStyle = typeStyles[type] || typeStyles.info

    // Determine if dismiss button should be shown
    const shouldShowDismiss = showDismiss !== undefined ? showDismiss : (autoClose === null)

    // Create content HTML
    const iconHtml = icon || currentTypeStyle.iconDefault
    const titleText = title || currentTypeStyle.titleDefault

    // Generate timestamp if time option is enabled
    let timeHtml = ''
    if (time) {
        const now = new Date()
        const year = now.getFullYear()
        const month = String(now.getMonth() + 1).padStart(2, '0')
        const day = String(now.getDate()).padStart(2, '0')
        const hours = String(now.getHours()).padStart(2, '0')
        const minutes = String(now.getMinutes()).padStart(2, '0')
        const seconds = String(now.getSeconds()).padStart(2, '0')
        const timestamp = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
        timeHtml = `<div class="uib-overlay-time" style="font-size: 0.8em; color: var(--text3, #999); margin-left: auto; margin-right: ${shouldShowDismiss ? '0.5rem' : '0'};">${timestamp}</div>`
    }

    overlayEntry.innerHTML = /* html */ `
        <div class="uib-overlay-entry" style="--callout-color:${currentTypeStyle.color};">
            <div class="uib-overlay-header">
                <div class="uib-overlay-icon">${iconHtml}</div>
                <div class="uib-overlay-title">${titleText}</div>
                ${timeHtml}
                ${shouldShowDismiss
                    ? `<button class="uib-overlay-dismiss" data-entry-id="${entryId}" title="Close">×</button>`
                    : ''}
            </div>
            <div class="uib-overlay-content">
                ${content}
            </div>
        </div>
    `

    // Add to overlay container at the top, sliding existing entries down
    if (overlayContainer.children.length > 0) {
        // Insert new entry at the top
        overlayContainer.insertBefore(overlayEntry, overlayContainer.firstChild)
    } else {
        // First entry, just add it normally
        overlayContainer.appendChild(overlayEntry)
    }

    // Close function for this specific entry
    const closeOverlayEntry = () => {
        const entry = document.getElementById(entryId)
        if (!entry) return

        entry.style.animation = 'slideOut 0.3s ease-in'
        setTimeout(() => {
            if (entry.parentNode) {
                entry.remove()
                // Remove the main container if no entries remain
                const container = document.getElementById(overlayContainerId)
                if (container && container.children.length === 0) {
                    container.remove()
                }
            }
        }, 300)
    }

    // Add dismiss button event listener
    const dismissBtn = overlayEntry.querySelector('.uib-overlay-dismiss')
    if (dismissBtn) {
        dismissBtn.addEventListener('click', closeOverlayEntry)
    }

    // Set up auto-close if specified
    let autoCloseTimer = null
    if (autoClose !== null && autoClose > 0) {
        autoCloseTimer = setTimeout(closeOverlayEntry, autoClose * 1000)
    }

    // Return control object
    return {
        close: () => {
            if (autoCloseTimer) {
                clearTimeout(autoCloseTimer)
            }
            closeOverlayEntry()
        },
        id: entryId,
    }
}