diff --git a/components/browser-upload.php b/components/browser-upload.php index fd06a54..69c575a 100644 --- a/components/browser-upload.php +++ b/components/browser-upload.php @@ -5,6 +5,22 @@ const android = /Android/i.test(navigator.userAgent); let uploadQueue = Promise.resolve(); window.ZoomzillaUpload = { + // Резерв из пяти точек задаётся CSS: слово и соседняя иконка не двигаются. + renderLoadingLabel(label, dots, text) { + if (!label) return; + let output = label.querySelector('[data-upload-dots]'); + if (!output) { + label.textContent = text + ' '; + const slot = document.createElement('span'); + slot.className = 'upload-loading-dots'; + slot.setAttribute('aria-hidden', 'true'); + output = document.createElement('span'); + output.dataset.uploadDots = ''; + slot.append(output); + label.append(slot); + } + output.textContent = '.'.repeat(dots); + }, bindPicker(form, mainInput, fullAccept, onFiles) { const mobile = android || /iPhone|iPad|iPod/i.test(navigator.userAgent) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1); if (mobile) form.dataset.mobileUpload = '1'; diff --git a/components/form.php b/components/form.php index c53df4a..f69af6f 100644 --- a/components/form.php +++ b/components/form.php @@ -105,7 +105,7 @@ $basePickerAccept = 'image/jpeg,image/png,image/gif,image/webp,image/bmp,image/a const uploadButtonDefaultLabel = uploadButtonLabel?.textContent || ''; function renderUploadButton() { - if (uploadButtonLabel) uploadButtonLabel.textContent = 'Загрузка' + '.'.repeat(uploadDots); + window.ZoomzillaUpload.renderLoadingLabel(uploadButtonLabel, uploadDots, ); } function beginUploadPending() { @@ -118,7 +118,7 @@ $basePickerAccept = 'image/jpeg,image/png,image/gif,image/webp,image/bmp,image/a uploadButton.setAttribute('aria-busy', 'true'); } uploadDotsTimer = window.setInterval(() => { - uploadDots = uploadDots === 5 ? 1 : uploadDots + 1; + uploadDots = (uploadDots + 1) % 6; renderUploadButton(); }, 500); return true; diff --git a/style.css b/style.css index e3d2067..7a25242 100644 --- a/style.css +++ b/style.css @@ -167,7 +167,7 @@ body { align-items: center; justify-content: center; padding: 4px 10px; - font: 700 18px/26px Inter, sans-serif; + font: 400 16px/26px Inter, sans-serif; color: #fff; backdrop-filter: none; -webkit-backdrop-filter: none; @@ -621,11 +621,13 @@ body { } .navbar-toggler .navbar-toggler-icon { - background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 1%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); + background-position: center; + background-repeat: no-repeat; + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 1%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); } .navbar-toggler:not(.collapsed) .navbar-toggler-icon { - background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 1%29' stroke-linecap='round' stroke-width='2' d='M6 6L24 23.9999M6 24L24 6.00015'/%3e%3c/svg%3e"); + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 1%29' stroke-linecap='round' stroke-width='2' d='M6 6L24 23.9999M6 24L24 6.00015'/%3e%3c/svg%3e"); } .theme-dark .link-icon { @@ -1561,6 +1563,11 @@ body { margin-top: 24px; } +/* Пять мест сохраняются и в нулевом кадре анимации загрузки. */ +.upload-loading-dots { display: inline-grid; text-align: left; } +.upload-loading-dots::before { content: '.....'; visibility: hidden; grid-area: 1 / 1; } +.upload-loading-dots > span { grid-area: 1 / 1; } + .dropzone-form-button { display: inline-flex; padding: 0 24px; @@ -2810,7 +2817,7 @@ body:not(.theme-dark) .theme-light-hidden { .index-mobile-fit .image-examples-label { display: none; } .index-mobile-fit .image-examples-list { gap: 8px; } .index-mobile-fit .image-examples-item { flex-basis: calc((100% - 32px) / 5); min-width: 0; } - .index-mobile-fit #image-compare .icv__label { top: 4px; bottom: auto; margin: 0; font: 600 9px/1.3 Inter, sans-serif; padding: 2px 5px; border: 1px solid rgb(255 255 255 / 65%); border-radius: 5px; background: rgb(67 72 82 / 72%); color: #fff; box-shadow: 0 1px 3px rgb(0 0 0 / 20%); text-shadow: 0 1px 1px rgb(0 0 0 / 35%); white-space: nowrap; } + .index-mobile-fit #image-compare .icv__label { top: 4px; bottom: auto; margin: 0; width: 48px; height: 20px; display: flex; align-items: center; justify-content: center; box-sizing: border-box; font: 600 9px/1.3 Inter, sans-serif; padding: 2px 5px; border: 1px solid rgb(255 255 255 / 65%); border-radius: 5px; background: rgb(67 72 82 / 72%); color: #fff; box-shadow: 0 1px 3px rgb(0 0 0 / 20%); text-shadow: 0 1px 1px rgb(0 0 0 / 35%); white-space: nowrap; } .index-mobile-fit #image-compare .icv__label-before { left: 24px; } .index-mobile-fit #image-compare .icv__label-after { right: 24px; } } @@ -2824,7 +2831,7 @@ body:not(.theme-dark) .theme-light-hidden { .footer-logo img{width:160px;height:auto;max-width:100%;} .header .btn-header{min-height:44px;height:44px;font-size:14px;line-height:20px;padding:0 16px;border-radius:12px;white-space:nowrap;gap:6px;} @media(max-width:767.98px){ - .header .navbar{height:68px;} .header .navbar-brand img{width:180px;} .header .navbar-toggler{width:30px;height:30px;border-radius:8px;padding:0;} .header .navbar-toggler-icon{width:20px;height:20px;background-size:20px;} + .header .navbar{height:68px;} .header .navbar-brand img{width:180px;} .header .navbar-toggler{width:30px;height:30px;border-radius:8px;padding:0;display:inline-flex;align-items:center;justify-content:center;} .header .navbar-toggler-icon{width:20px;height:20px;background-size:20px;display:block;} .header .navbar-brand{margin-right:8px;} .header .btn-header{height:30px;min-height:30px;font-size:12px;padding:0 12px;border-radius:11px;} .header .btn-header svg{width:16px;height:16px;} diff --git a/style.min.c.css b/style.min.c.css index 0305c8b..5a21363 100644 --- a/style.min.c.css +++ b/style.min.c.css @@ -794,7 +794,7 @@ padding-top: 2svh !important; .index-mobile-fit .image-examples-label { display: none; } .index-mobile-fit .image-examples-list { gap: 8px; } .index-mobile-fit .image-examples-item { flex-basis: calc((100% - 32px) / 5); min-width: 0; } - .index-mobile-fit #image-compare .icv__label { top: 4px; bottom: auto; margin: 0; font: 600 9px/1.3 Inter, sans-serif; padding: 2px 5px; border: 1px solid rgb(255 255 255 / 65%); border-radius: 5px; background: rgb(67 72 82 / 72%); color: #fff; box-shadow: 0 1px 3px rgb(0 0 0 / 20%); text-shadow: 0 1px 1px rgb(0 0 0 / 35%); white-space: nowrap; } + .index-mobile-fit #image-compare .icv__label { top: 4px; bottom: auto; margin: 0; width: 48px; height: 20px; display: flex; align-items: center; justify-content: center; box-sizing: border-box; font: 600 9px/1.3 Inter, sans-serif; padding: 2px 5px; border: 1px solid rgb(255 255 255 / 65%); border-radius: 5px; background: rgb(67 72 82 / 72%); color: #fff; box-shadow: 0 1px 3px rgb(0 0 0 / 20%); text-shadow: 0 1px 1px rgb(0 0 0 / 35%); white-space: nowrap; } .index-mobile-fit #image-compare .icv__label-before { left: 24px; } .index-mobile-fit #image-compare .icv__label-after { right: 24px; } } @@ -808,7 +808,7 @@ padding-top: 2svh !important; .footer-logo img{width:160px;height:auto;max-width:100%;} .header .btn-header{min-height:44px;height:44px;font-size:14px;line-height:20px;padding:0 16px;border-radius:12px;white-space:nowrap;gap:6px;} @media(max-width:767.98px){ - .header .navbar{height:68px;} .header .navbar-brand img{width:180px;} .header .navbar-toggler{width:30px;height:30px;border-radius:8px;padding:0;} .header .navbar-toggler-icon{width:20px;height:20px;background-size:20px;} + .header .navbar{height:68px;} .header .navbar-brand img{width:180px;} .header .navbar-toggler{width:30px;height:30px;border-radius:8px;padding:0;display:inline-flex;align-items:center;justify-content:center;} .header .navbar-toggler-icon{width:20px;height:20px;background-size:20px;display:block;} .header .navbar-brand{margin-right:8px;} .header .btn-header{height:30px;min-height:30px;font-size:12px;padding:0 12px;border-radius:11px;} .header .btn-header svg{width:16px;height:16px;} @@ -839,4 +839,5 @@ padding-top: 2svh !important; .tour-processing #preview, .main-section:has(#process:not([style*="display: none"])) #preview{height:clamp(220px,calc(100svh - 335px),380px)!important;margin-top:16px;} } @media(max-width:767.98px){.result-download-title{font-size:24px;line-height:1.2;}} -@media (min-width:768px){.image-compare .icv__label{top:10px;width:92px;height:36px;display:flex;align-items:center;justify-content:center;padding:4px 10px;font:700 18px/26px Inter,sans-serif;color:#fff;backdrop-filter:none;-webkit-backdrop-filter:none;background:rgb(0 0 0 / 25%);border:1px solid rgb(255 255 255 / 80%);box-shadow:none;text-shadow:none;}} +@media (min-width:768px){.image-compare .icv__label{top:10px;width:92px;height:36px;display:flex;align-items:center;justify-content:center;padding:4px 10px;font:400 16px/26px Inter,sans-serif;color:#fff;backdrop-filter:none;-webkit-backdrop-filter:none;background:rgb(0 0 0 / 25%);border:1px solid rgb(255 255 255 / 80%);box-shadow:none;text-shadow:none;}} +.upload-loading-dots{display:inline-grid;text-align:left;}.upload-loading-dots::before{content:'.....';visibility:hidden;grid-area:1 / 1;}.upload-loading-dots > span{grid-area:1 / 1;} diff --git a/style.min.css b/style.min.css index 1f0a19f..5884225 100644 --- a/style.min.css +++ b/style.min.css @@ -16,7 +16,7 @@ .index-mobile-fit .image-examples-label { display: none; } .index-mobile-fit .image-examples-list { gap: 8px; } .index-mobile-fit .image-examples-item { flex-basis: calc((100% - 32px) / 5); min-width: 0; } - .index-mobile-fit #image-compare .icv__label { top: 4px; bottom: auto; margin: 0; font: 600 9px/1.3 Inter, sans-serif; padding: 2px 5px; border: 1px solid rgb(255 255 255 / 65%); border-radius: 5px; background: rgb(67 72 82 / 72%); color: #fff; box-shadow: 0 1px 3px rgb(0 0 0 / 20%); text-shadow: 0 1px 1px rgb(0 0 0 / 35%); white-space: nowrap; } + .index-mobile-fit #image-compare .icv__label { top: 4px; bottom: auto; margin: 0; width: 48px; height: 20px; display: flex; align-items: center; justify-content: center; box-sizing: border-box; font: 600 9px/1.3 Inter, sans-serif; padding: 2px 5px; border: 1px solid rgb(255 255 255 / 65%); border-radius: 5px; background: rgb(67 72 82 / 72%); color: #fff; box-shadow: 0 1px 3px rgb(0 0 0 / 20%); text-shadow: 0 1px 1px rgb(0 0 0 / 35%); white-space: nowrap; } .index-mobile-fit #image-compare .icv__label-before { left: 24px; } .index-mobile-fit #image-compare .icv__label-after { right: 24px; } } @@ -30,7 +30,7 @@ .footer-logo img{width:160px;height:auto;max-width:100%;} .header .btn-header{min-height:44px;height:44px;font-size:14px;line-height:20px;padding:0 16px;border-radius:12px;white-space:nowrap;gap:6px;} @media(max-width:767.98px){ - .header .navbar{height:68px;} .header .navbar-brand img{width:180px;} .header .navbar-toggler{width:30px;height:30px;border-radius:8px;padding:0;} .header .navbar-toggler-icon{width:20px;height:20px;background-size:20px;} + .header .navbar{height:68px;} .header .navbar-brand img{width:180px;} .header .navbar-toggler{width:30px;height:30px;border-radius:8px;padding:0;display:inline-flex;align-items:center;justify-content:center;} .header .navbar-toggler-icon{width:20px;height:20px;background-size:20px;display:block;} .header .navbar-brand{margin-right:8px;} .header .btn-header{height:30px;min-height:30px;font-size:12px;padding:0 12px;border-radius:11px;} .header .btn-header svg{width:16px;height:16px;} @@ -61,4 +61,5 @@ .tour-processing #preview, .main-section:has(#process:not([style*="display: none"])) #preview{height:clamp(220px,calc(100svh - 335px),380px)!important;margin-top:16px;} } @media(max-width:767.98px){.result-download-title{font-size:24px;line-height:1.2;}} -@media (min-width:768px){.image-compare .icv__label{top:10px;width:92px;height:36px;display:flex;align-items:center;justify-content:center;padding:4px 10px;font:700 18px/26px Inter,sans-serif;color:#fff;backdrop-filter:none;-webkit-backdrop-filter:none;background:rgb(0 0 0 / 25%);border:1px solid rgb(255 255 255 / 80%);box-shadow:none;text-shadow:none;}} +@media (min-width:768px){.image-compare .icv__label{top:10px;width:92px;height:36px;display:flex;align-items:center;justify-content:center;padding:4px 10px;font:400 16px/26px Inter,sans-serif;color:#fff;backdrop-filter:none;-webkit-backdrop-filter:none;background:rgb(0 0 0 / 25%);border:1px solid rgb(255 255 255 / 80%);box-shadow:none;text-shadow:none;}} +.upload-loading-dots{display:inline-grid;text-align:left;}.upload-loading-dots::before{content:'.....';visibility:hidden;grid-area:1 / 1;}.upload-loading-dots > span{grid-area:1 / 1;}