diff --git a/public/css/app.css b/public/css/app.css index 4312ab0..46b255d 100644 --- a/public/css/app.css +++ b/public/css/app.css @@ -20,4 +20,33 @@ footer { #copy { text-decoration: none; + } + + /* Simple, clean loading indicator (no spinner spam) */ + .loading-indicator { + display: flex; + justify-content: center; + align-items: center; + gap: 0.35rem; + padding: 2rem 0; + } + + .loading-dots { + display: inline-flex; + gap: 0.15rem; + } + + .loading-dots span { + display: inline-block; + opacity: 0.2; + transform: translateY(-1px); + animation: loading-dot 1.1s infinite ease-in-out; + } + + .loading-dots span:nth-child(2) { animation-delay: 0.15s; } + .loading-dots span:nth-child(3) { animation-delay: 0.30s; } + + @keyframes loading-dot { + 0%, 80%, 100% { opacity: 0.2; } + 40% { opacity: 1; } } \ No newline at end of file diff --git a/public/js/app_checklist.js b/public/js/app_checklist.js index b5ee5a4..de2935f 100644 --- a/public/js/app_checklist.js +++ b/public/js/app_checklist.js @@ -8,11 +8,9 @@ window.onload = async function () { movieTableBody.innerHTML = ` -
-
- Chargement... -
- Chargement… +
+ Chargement +
@@ -20,15 +18,11 @@ window.onload = async function () { } function setInlineLoading(el, label = 'Chargement…') { + // Keep the header clean: no inline spinners, just text. if (!el) return; - el.innerHTML = ` - - - Chargement... - - ${label} - - `; + el.textContent = label; + el.setAttribute('aria-live', 'polite'); + el.setAttribute('aria-busy', 'true'); } function showTableError(message) { @@ -224,9 +218,7 @@ window.onload = async function () { showTableLoading(); setInlineLoading(watchedRatioEl); const progressBarEl = document.getElementById('progress-bar'); - if (progressBarEl) { - progressBarEl.classList.add('progress-bar-striped', 'progress-bar-animated'); - } + // Avoid extra "loading" animations; the table loader is enough. let movies = []; let watchedMovies = []; @@ -270,9 +262,7 @@ window.onload = async function () { const summary = await summaryPromise; watchedMovies = Array.isArray(summary?.watchedMovies) ? summary.watchedMovies : []; - if (progressBarEl) { - progressBarEl.classList.remove('progress-bar-striped', 'progress-bar-animated'); - } + if (progressBarEl) progressBarEl.removeAttribute('aria-busy'); } catch (e) { showTableError('Impossible de charger la checklist. Réessaie dans quelques instants.'); return; diff --git a/public/js/app_movies.js b/public/js/app_movies.js index 4456303..fec4bc6 100644 --- a/public/js/app_movies.js +++ b/public/js/app_movies.js @@ -2,24 +2,19 @@ window.onload = async function () { function setLoading(el) { if (!el) return; el.innerHTML = ` -
-
- Chargement... -
+
+ Chargement +
`; } function setInlineLoading(el, label = 'Chargement…') { + // Keep the header clean: no inline spinners, just text. if (!el) return; - el.innerHTML = ` - - - Chargement... - - ${label} - - `; + el.textContent = label; + el.setAttribute('aria-live', 'polite'); + el.setAttribute('aria-busy', 'true'); } function setLoadError(el, message) {