Add To Cart Snippets

Collection of Add To Cart PopUp Snippet.

Modern ecommerce Add To Cart PopUP confirmation modal with view cart and checkout actions
Modern ecommerce Add To Cart PopUP confirmation modal with view cart and checkout actions
<?php
/**
 * Plugin Name: Added to Cart Popup
 * Description: Shows a stylish popup notification when a product is added to the WooCommerce cart.
 * Version: 1.0.0
 * Author: Your Name
 * Requires at least: 5.0
 * Requires PHP: 7.4
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

/**
 * Inject the popup HTML into the footer.
 */
add_action( 'wp_footer', 'atcp_render_popup_html' );
function atcp_render_popup_html() {
    if ( ! function_exists( 'WC' ) ) return;
    ?>
    <div id="atcp-overlay" aria-hidden="true"></div>
    <div id="atcp-popup" role="dialog" aria-modal="true" aria-label="Item added to cart" aria-hidden="true">
        <div class="atcp-icon-wrap">
            <svg class="atcp-check-icon" viewBox="0 0 52 52" fill="none" xmlns="http://www.w3.org/2000/svg">
                <circle class="atcp-check-circle" cx="26" cy="26" r="24" stroke="currentColor" stroke-width="3" fill="none"/>
                <path class="atcp-check-mark" d="M14 27L22 35L38 18" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
            </svg>
        </div>
        <div class="atcp-content">
            <p class="atcp-label">Added to Cart</p>
            <p class="atcp-product-name" id="atcp-product-name"></p>
            <p class="atcp-quantity" id="atcp-quantity"></p>
        </div>
        <div class="atcp-actions">
            <a href="<?php echo esc_url( wc_get_cart_url() ); ?>" class="atcp-btn atcp-btn-primary">View Cart</a>
            <a href="<?php echo esc_url( wc_get_checkout_url() ); ?>" class="atcp-btn atcp-btn-secondary">Checkout</a>
        </div>
        <button class="atcp-close" id="atcp-close" aria-label="Close popup">&times;</button>
        <div class="atcp-progress-bar" id="atcp-progress-bar"></div>
    </div>
    <?php
}

/**
 * Enqueue styles and scripts.
 */
add_action( 'wp_enqueue_scripts', 'atcp_enqueue_assets' );
function atcp_enqueue_assets() {
    if ( ! function_exists( 'WC' ) ) return;

    // Inline CSS
    $css = '
        /* ── Reset & Base ── */
        #atcp-overlay {
            display: none;
            position: fixed;
            inset: 0;
            background: rgba(0,0,0,0.35);
            backdrop-filter: blur(3px);
            -webkit-backdrop-filter: blur(3px);
            z-index: 99998;
            opacity: 0;
            transition: opacity 0.3s ease;
        }
        #atcp-overlay.atcp-visible {
            opacity: 1;
        }

        /* ── Popup Card ── */
        #atcp-popup {
            display: none;
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -44%) scale(0.92);
            width: min(420px, 92vw);
            background: #ffffff;
            border-radius: 20px;
            padding: 36px 32px 28px;
            box-shadow:
                0 30px 80px rgba(0,0,0,0.18),
                0 8px 24px rgba(0,0,0,0.10);
            z-index: 99999;
            opacity: 0;
            transition: opacity 0.35s cubic-bezier(.22,.68,0,1.3),
                        transform 0.35s cubic-bezier(.22,.68,0,1.3);
            overflow: hidden;
            font-family: -apple-system, "Segoe UI", Helvetica, Arial, sans-serif;
        }
        #atcp-popup.atcp-visible {
            opacity: 1;
            transform: translate(-50%, -50%) scale(1);
        }

        /* ── Check Icon ── */
        .atcp-icon-wrap {
            display: flex;
            justify-content: center;
            margin-bottom: 18px;
        }
        .atcp-check-icon {
            width: 56px;
            height: 56px;
            color: #22c55e;
        }
        .atcp-check-circle {
            stroke-dasharray: 157;
            stroke-dashoffset: 157;
            transition: stroke-dashoffset 0.55s ease 0.15s;
        }
        .atcp-check-mark {
            stroke-dasharray: 40;
            stroke-dashoffset: 40;
            transition: stroke-dashoffset 0.35s ease 0.55s;
        }
        #atcp-popup.atcp-visible .atcp-check-circle,
        #atcp-popup.atcp-visible .atcp-check-mark {
            stroke-dashoffset: 0;
        }

        /* ── Text Content ── */
        .atcp-content {
            text-align: center;
            margin-bottom: 22px;
        }
        .atcp-label {
            font-size: 12px;
            font-weight: 700;
            letter-spacing: 0.12em;
            text-transform: uppercase;
            color: #22c55e;
            margin: 0 0 6px;
        }
        .atcp-product-name {
            font-size: 17px;
            font-weight: 600;
            color: #111827;
            margin: 0 0 4px;
            line-height: 1.35;
        }
        .atcp-quantity {
            font-size: 13px;
            color: #6b7280;
            margin: 0;
        }

        /* ── Action Buttons ── */
        .atcp-actions {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 10px;
        }
        .atcp-btn {
            display: block;
            text-align: center;
            text-decoration: none;
            font-size: 14px;
            font-weight: 600;
            padding: 12px 0;
            border-radius: 10px;
            transition: transform 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
            cursor: pointer;
        }
        .atcp-btn:hover {
            transform: translateY(-1px);
        }
        .atcp-btn-primary {
            background: #111827;
            color: #ffffff;
            box-shadow: 0 4px 14px rgba(17,24,39,0.25);
        }
        .atcp-btn-primary:hover {
            background: #1f2937;
            box-shadow: 0 6px 18px rgba(17,24,39,0.32);
        }
        .atcp-btn-secondary {
            background: #f3f4f6;
            color: #374151;
        }
        .atcp-btn-secondary:hover {
            background: #e5e7eb;
        }

        /* ── Close Button ── */
        .atcp-close {
            position: absolute;
            top: 14px;
            right: 16px;
            background: none;
            border: none;
            font-size: 22px;
            line-height: 1;
            color: #9ca3af;
            cursor: pointer;
            padding: 4px 6px;
            border-radius: 6px;
            transition: color 0.15s ease, background 0.15s ease;
        }
        .atcp-close:hover {
            color: #374151;
            background: #f3f4f6;
        }

        /* ── Auto-close Progress Bar ── */
        .atcp-progress-bar {
            position: absolute;
            bottom: 0;
            left: 0;
            height: 3px;
            width: 100%;
            background: #22c55e;
            transform-origin: left;
            transform: scaleX(0);
        }
        .atcp-progress-bar.atcp-running {
            animation: atcp-progress linear forwards;
        }
        @keyframes atcp-progress {
            from { transform: scaleX(1); }
            to   { transform: scaleX(0); }
        }

        /* ── Mobile ── */
        @media (max-width: 480px) {
            #atcp-popup { padding: 28px 20px 22px; border-radius: 16px; }
            .atcp-actions { grid-template-columns: 1fr; }
        }
    ';
    wp_add_inline_style( 'woocommerce-general', $css );

    // Inline JS
    $auto_close_ms = 4500; // milliseconds before auto-close
    $js = '
    (function() {
        var AUTO_CLOSE_MS = ' . intval( $auto_close_ms ) . ';
        var popup    = document.getElementById("atcp-popup");
        var overlay  = document.getElementById("atcp-overlay");
        var closeBtn = document.getElementById("atcp-close");
        var nameEl   = document.getElementById("atcp-product-name");
        var qtyEl    = document.getElementById("atcp-quantity");
        var bar      = document.getElementById("atcp-progress-bar");
        var timer    = null;

        if (!popup) return;

        function openPopup(productName, qty) {
            clearTimeout(timer);

            nameEl.textContent = productName || "Your item";
            qtyEl.textContent  = qty ? "Quantity: " + qty : "";

            // Reset progress bar
            bar.classList.remove("atcp-running");
            bar.style.animationDuration = "";
            void bar.offsetWidth; // reflow

            // Show
            overlay.style.display = "block";
            popup.style.display   = "block";
            void popup.offsetWidth; // reflow to trigger transition
            popup.classList.add("atcp-visible");
            overlay.classList.add("atcp-visible");
            popup.setAttribute("aria-hidden", "false");

            // Start auto-close bar
            bar.style.animationDuration = AUTO_CLOSE_MS + "ms";
            bar.classList.add("atcp-running");

            timer = setTimeout(closePopup, AUTO_CLOSE_MS);
        }

        function closePopup() {
            clearTimeout(timer);
            popup.classList.remove("atcp-visible");
            overlay.classList.remove("atcp-visible");
            popup.setAttribute("aria-hidden", "true");
            setTimeout(function() {
                popup.style.display  = "none";
                overlay.style.display = "none";
                bar.classList.remove("atcp-running");
            }, 350);
        }

        // Close on button / overlay click
        closeBtn.addEventListener("click", closePopup);
        overlay.addEventListener("click", closePopup);

        // Close on Escape key
        document.addEventListener("keydown", function(e) {
            if (e.key === "Escape") closePopup();
        });

        // ── WooCommerce AJAX add-to-cart event ──
        // Fired by WooCommerce core after a successful AJAX add-to-cart.
        jQuery(document.body).on("added_to_cart", function(e, fragments, cart_hash, $btn) {
            var productName = "";
            var qty         = 1;

            if ($btn && $btn.length) {
                productName = $btn.closest(".product").find(".woocommerce-loop-product__title").first().text().trim()
                           || $btn.data("product_name")
                           || $btn.attr("data-product_name")
                           || "";
                qty = $btn.data("quantity") || 1;
            }
            openPopup(productName, qty);
        });

        // ── Single product page (non-AJAX, form submit) ──
        // Detect ?added-to-cart= in URL on page load.
        var params = new URLSearchParams(window.location.search);
        if (params.has("added-to-cart")) {
            var productId = params.get("added-to-cart");
            // Fetch product title via WooCommerce REST API (public endpoint, no auth needed)
            fetch(atcpData.restUrl + "wc/store/v1/products/" + productId)
                .then(function(r) { return r.ok ? r.json() : null; })
                .then(function(data) {
                    var name = data && data.name ? data.name : "Your item";
                    openPopup(name, 1);
                })
                .catch(function() { openPopup("Your item", 1); });
        }
    })();
    ';

    wp_add_inline_script( 'wc-add-to-cart', $js );

    // Pass REST URL to JS
    wp_localize_script( 'wc-add-to-cart', 'atcpData', [
        'restUrl' => esc_url_raw( rest_url() ),
    ]);
}