diff --git a/public/css/banner-frontend.css b/public/css/banner-frontend.css index fcd1207..9b77583 100644 --- a/public/css/banner-frontend.css +++ b/public/css/banner-frontend.css @@ -1,112 +1,178 @@ -.sodino-banner { +.sodino-banner-wrap { direction: rtl; position: relative; - z-index: 9999; - font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; -} - -.sodino-banner-wrap { - margin: 0 auto; - max-width: 1200px; - padding: 18px 22px; + z-index: 99990; + box-sizing: border-box; + margin: 18px auto; + width: min(1120px, calc(100% - 32px)); + padding: 18px; + overflow: hidden; + color: #172033; background: #ffffff; - border: 1px solid rgba(148, 163, 184, 0.35); - border-radius: 1rem; - box-shadow: 0 18px 35px rgba(15, 23, 42, 0.08); + border: 1px solid rgba(15, 23, 42, 0.12); + border-radius: 18px; + box-shadow: 0 18px 45px rgba(15, 23, 42, 0.14); + font-family: inherit; } -.sodino-banner-top { +.sodino-banner-wrap *, +.sodino-banner-wrap *::before, +.sodino-banner-wrap *::after { + box-sizing: border-box; +} + +.sodino-banner-content { + display: flex; + align-items: center; + justify-content: center; + min-height: 64px; +} + +.sodino-banner-link { + display: block; + width: 100%; + color: inherit; + text-decoration: none; + cursor: pointer; +} + +.sodino-banner-link:hover, +.sodino-banner-link:focus { + color: inherit; + text-decoration: none; +} + +.sodino-banner-link:focus-visible { + outline: 3px solid rgba(37, 99, 235, 0.35); + outline-offset: 4px; + border-radius: 14px; +} + +.sodino-banner-image { + display: block; + width: 100%; + height: auto; + max-height: min(420px, 70vh); + object-fit: cover; + border-radius: 14px; +} + +.sodino-banner-close { + position: absolute; + top: 12px; + left: 12px; + z-index: 3; + display: inline-flex; + align-items: center; + justify-content: center; + width: 38px; + height: 38px; + padding: 0; + color: #0f172a; + background: rgba(255, 255, 255, 0.94); + border: 1px solid rgba(15, 23, 42, 0.14); + border-radius: 999px; + box-shadow: 0 10px 24px rgba(15, 23, 42, 0.18); + font-size: 26px; + line-height: 1; + cursor: pointer; + transition: background-color 160ms ease, border-color 160ms ease, transform 160ms ease; +} + +.sodino-banner-close:hover, +.sodino-banner-close:focus { + background: #ffffff; + border-color: rgba(15, 23, 42, 0.28); + transform: translateY(-1px); +} + +.sodino-banner-close:focus-visible { + outline: 3px solid rgba(37, 99, 235, 0.35); + outline-offset: 2px; +} + +.sodino-banner-backdrop { position: fixed; - top: 20px; - left: 50%; - transform: translateX(-50%); - width: calc(100% - 32px); - max-width: 1100px; -} - -.sodino-banner-bottom { - position: fixed; - bottom: 20px; - left: 50%; - transform: translateX(-50%); - width: calc(100% - 32px); - max-width: 1100px; -} - -.sodino-banner-floating_bar { - position: fixed; - left: 50%; - transform: translateX(-50%); - width: calc(100% - 32px); - max-width: 1100px; -} - -.sodino-banner-position-top.sodino-banner-floating_bar, -.sodino-banner-position-middle.sodino-banner-floating_bar { - top: 20px; -} - -.sodino-banner-position-bottom.sodino-banner-floating_bar, -.sodino-banner-position-cart.sodino-banner-floating_bar, -.sodino-banner-position-product_page.sodino-banner-floating_bar { - bottom: 20px; + inset: 0; + z-index: 99989; + background: rgba(15, 23, 42, 0.46); + backdrop-filter: blur(3px); } .sodino-banner-popup { position: fixed; top: 50%; left: 50%; + width: min(680px, calc(100% - 32px)); + max-height: calc(100vh - 32px); + margin: 0; + padding: 46px 18px 18px; + overflow: auto; transform: translate(-50%, -50%); - max-width: 95%; - width: 680px; - background: #ffffff; - box-shadow: 0 30px 60px rgba(15, 23, 42, 0.12); + border-radius: 24px; + box-shadow: 0 28px 90px rgba(15, 23, 42, 0.28); } -.sodino-banner-close { - position: absolute; - top: 14px; - right: 16px; - background: rgba(15, 23, 42, 0.06); - border: none; - color: #0f172a; - width: 36px; - height: 36px; - border-radius: 9999px; - font-size: 1.2rem; - cursor: pointer; +.sodino-banner-popup .sodino-banner-content { + min-height: 120px; } -.sodino-banner-content { - display: flex; - justify-content: center; - align-items: center; - gap: 20px; - flex-wrap: wrap; +.sodino-banner-popup .sodino-banner-image { + max-height: min(560px, 72vh); + border-radius: 18px; } -.sodino-banner-image { - width: 100%; - height: auto; - border-radius: 1rem; - display: block; +.sodino-banner-floating_bar, +.sodino-banner-position-top.sodino-banner-inline, +.sodino-banner-position-bottom.sodino-banner-inline { + position: fixed; + left: 50%; + width: min(1040px, calc(100% - 32px)); + margin: 0; + transform: translateX(-50%); } -.sodino-banner-link { - display: inline-block; +.sodino-banner-position-top.sodino-banner-floating_bar, +.sodino-banner-position-top.sodino-banner-inline { + top: 18px; +} + +.sodino-banner-position-bottom.sodino-banner-floating_bar, +.sodino-banner-position-bottom.sodino-banner-inline, +.sodino-banner-position-cart.sodino-banner-floating_bar, +.sodino-banner-position-product_page.sodino-banner-floating_bar { + bottom: 18px; +} + +.sodino-banner-position-middle.sodino-banner-floating_bar { + top: 18px; } @media (max-width: 768px) { - .sodino-banner-top, - .sodino-banner-bottom, - .sodino-banner-floating_bar, - .sodino-banner-popup { + .sodino-banner-wrap { width: calc(100% - 20px); - left: 50%; - transform: translateX(-50%); + padding: 14px; + border-radius: 16px; } .sodino-banner-popup { - max-width: 95%; + width: calc(100% - 20px); + padding: 44px 12px 12px; + border-radius: 20px; + transform: translate(-50%, -50%); + } + + .sodino-banner-floating_bar, + .sodino-banner-position-top.sodino-banner-inline, + .sodino-banner-position-bottom.sodino-banner-inline { + width: calc(100% - 20px); + } + + .sodino-banner-close { + top: 9px; + left: 9px; + width: 34px; + height: 34px; + font-size: 24px; } } diff --git a/public/hooks/banner-hooks.php b/public/hooks/banner-hooks.php index 3ae6509..9bc50fd 100644 --- a/public/hooks/banner-hooks.php +++ b/public/hooks/banner-hooks.php @@ -44,10 +44,11 @@ function sodino_get_banner_html($banner) { switch ($banner->content_type) { case 'image': $image = esc_url($banner->content_value); + $image_html = '' . esc_attr($banner->title) . ''; if (!empty($banner->link_url)) { - $content = sprintf('%s', esc_url($banner->link_url), esc_attr($banner->id), '' . esc_attr($banner->title) . ''); + $content = sprintf('%s', esc_url($banner->link_url), esc_attr($banner->id), $image_html); } else { - $content = '' . esc_attr($banner->title) . ''; + $content = $image_html; } break; case 'shortcode': @@ -64,14 +65,15 @@ function sodino_get_banner_html($banner) { $linkAttributes = sprintf(' data-banner-id="%d" href="%s" class="sodino-banner-link"', esc_attr($banner->id), esc_url($banner->link_url)); } - $closeButton = ''; + $closeButton = ''; $wrapperClass = 'sodino-banner-wrap sodino-banner-' . esc_attr($banner->display_type) . ' sodino-banner-position-' . esc_attr($banner->position); $style = $banner->display_type === 'popup' ? 'style="display:none;"' : ''; - $html .= '
'; - if ($banner->display_type === 'popup' || $banner->display_type === 'floating_bar') { - $html .= $closeButton; + if ($banner->display_type === 'popup') { + $html .= ''; } + $html .= '
'; + $html .= $closeButton; $html .= '
'; if ($banner->content_type !== 'image' && !empty($banner->link_url)) { $html .= '' . $content . ''; diff --git a/public/js/banner-frontend.js b/public/js/banner-frontend.js index 3b56c89..a30acba 100644 --- a/public/js/banner-frontend.js +++ b/public/js/banner-frontend.js @@ -1,5 +1,4 @@ (function () { - const closeButtons = document.querySelectorAll('.sodino-banner-close'); const clicked = new Set(); function getCookie(name) { @@ -11,6 +10,24 @@ return null; } + function hideBanner(banner) { + if (!banner) { + return; + } + + banner.style.display = 'none'; + banner.setAttribute('aria-hidden', 'true'); + + const bannerId = banner.dataset.bannerId; + if (bannerId) { + const backdrop = document.querySelector('.sodino-banner-backdrop[data-banner-backdrop="' + bannerId + '"]'); + if (backdrop) { + backdrop.style.display = 'none'; + } + document.cookie = 'sodino_banner_' + bannerId + '=hidden; path=/; max-age=' + 60 * 60 * 24; + } + } + function sendClick(bannerId) { if (!bannerId || clicked.has(bannerId) || !window.sodinoBannerFrontend) { return; @@ -21,45 +38,69 @@ fetch(window.sodinoBannerFrontend.ajaxUrl, { method: 'POST', credentials: 'same-origin', + keepalive: true, headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' }, body: 'action=sodino_banner_click&banner_id=' + encodeURIComponent(bannerId) + '&nonce=' + encodeURIComponent(window.sodinoBannerFrontend.nonce), - }); + }).catch(function () {}); } document.addEventListener('click', function (event) { + const closeButton = event.target.closest('.sodino-banner-close'); + if (closeButton) { + event.preventDefault(); + event.stopPropagation(); + hideBanner(closeButton.closest('.sodino-banner-wrap')); + return; + } + + const backdrop = event.target.closest('.sodino-banner-backdrop'); + if (backdrop) { + event.preventDefault(); + const banner = document.querySelector('.sodino-banner-wrap[data-banner-id="' + backdrop.dataset.bannerBackdrop + '"]'); + hideBanner(banner); + return; + } + const target = event.target.closest('.sodino-banner-link'); if (target) { - const bannerId = target.dataset.bannerId; - sendClick(bannerId); + sendClick(target.dataset.bannerId); } }); - closeButtons.forEach(function (button) { - button.addEventListener('click', function () { - const wrapper = this.closest('.sodino-banner-wrap'); - if (!wrapper) { - return; - } - wrapper.style.display = 'none'; - const bannerId = wrapper.dataset.bannerId; - if (bannerId) { - document.cookie = 'sodino_banner_' + bannerId + '=hidden; path=/; max-age=' + 60 * 60 * 24; - } - }); + document.addEventListener('keydown', function (event) { + if (event.key !== 'Escape') { + return; + } + + const popup = document.querySelector('.sodino-banner-popup:not([aria-hidden="true"])'); + if (popup) { + hideBanner(popup); + } }); document.querySelectorAll('.sodino-banner-wrap').forEach(function (banner) { const bannerId = banner.dataset.bannerId; if (getCookie('sodino_banner_' + bannerId) === 'hidden') { banner.style.display = 'none'; + banner.setAttribute('aria-hidden', 'true'); + const backdrop = document.querySelector('.sodino-banner-backdrop[data-banner-backdrop="' + bannerId + '"]'); + if (backdrop) { + backdrop.style.display = 'none'; + } + return; } if (banner.classList.contains('sodino-banner-popup')) { setTimeout(function () { if (getCookie('sodino_banner_' + bannerId) !== 'hidden') { + const backdrop = document.querySelector('.sodino-banner-backdrop[data-banner-backdrop="' + bannerId + '"]'); + if (backdrop) { + backdrop.style.display = 'block'; + } banner.style.display = 'block'; + banner.setAttribute('aria-hidden', 'false'); } - }, 2000); + }, 900); } }); })();