diff --git a/internal/ajean/ui/index.html b/internal/ajean/ui/index.html index 41538bf..7f0ab2b 100644 --- a/internal/ajean/ui/index.html +++ b/internal/ajean/ui/index.html @@ -816,10 +816,12 @@ textarea.sctl{min-height:76px;resize:vertical;line-height:1.5} /* Modale ouverte mais pas encore remplie : on affiche le voile de chargement À LA PLACE du formulaire et du pied. Estomper le formulaire ne suffisait pas — on voyait quand même les champs s'écrire un par un derrière le voile. */ -/* Fond TRANSPARENT : le formulaire est déjà rendu invisible par `visibility`, - un fond opaque ne servirait qu'à masquer aussi le titre de la modale. */ -.modal-load{display:none;position:absolute;inset:0;z-index:2;align-items:center;justify-content:center; - pointer-events:none} +/* Voile OPAQUE, posé sous l'en-tête (le titre reste lisible) : `visibility:hidden` + sur le formulaire suffirait en théorie, mais un fond plein garantit qu'aucun + reste du preset précédent (moteur coché, réglages) ne puisse apparaître une + fraction de seconde. --mh = hauteur mesurée de l'en-tête, posée à l'ouverture. */ +.modal-load{display:none;position:absolute;inset:var(--mh,52px) 0 0 0;z-index:2; + align-items:center;justify-content:center;background:var(--bg);border-radius:0 0 12px 12px} .modal-ov.loading .modal-load{display:flex} /* visibility (et non display) : le formulaire garde sa place, donc la carte a déjà sa taille finale — la révéler ne provoque plus d'à-coup de hauteur. */ @@ -2480,8 +2482,13 @@ async function openItem(kind, key){ rawToggle.style.display = 'none'; rawBody.style.display = ''; } - document.getElementById('modal').classList.add('loading'); + const modalEl=document.getElementById('modal'); + modalEl.classList.add('loading'); showModal('modal'); + // Le voile s'arrête au bas de l'en-tête : on lui passe sa hauteur réelle. ⚠️ À + // mesurer APRÈS l'affichage — un élément en display:none mesure 0. + const mHead=modalEl.querySelector('.modal-head'); + if(mHead) modalEl.querySelector('.modal-card').style.setProperty('--mh', mHead.offsetHeight+'px'); // ⚠️ APRÈS showModal, jamais avant : le corps de la modale est un conteneur // défilant RÉUTILISÉ d'une ouverture à l'autre, et écrire scrollTop sur un // élément en display:none ne fait RIEN (il n'a pas de boîte de rendu) — le diff --git a/internal/ajean/ui/src/js/07-models.js b/internal/ajean/ui/src/js/07-models.js index bfaa09a..17de80a 100644 --- a/internal/ajean/ui/src/js/07-models.js +++ b/internal/ajean/ui/src/js/07-models.js @@ -102,8 +102,13 @@ async function openItem(kind, key){ rawToggle.style.display = 'none'; rawBody.style.display = ''; } - document.getElementById('modal').classList.add('loading'); + const modalEl=document.getElementById('modal'); + modalEl.classList.add('loading'); showModal('modal'); + // Le voile s'arrête au bas de l'en-tête : on lui passe sa hauteur réelle. ⚠️ À + // mesurer APRÈS l'affichage — un élément en display:none mesure 0. + const mHead=modalEl.querySelector('.modal-head'); + if(mHead) modalEl.querySelector('.modal-card').style.setProperty('--mh', mHead.offsetHeight+'px'); // ⚠️ APRÈS showModal, jamais avant : le corps de la modale est un conteneur // défilant RÉUTILISÉ d'une ouverture à l'autre, et écrire scrollTop sur un // élément en display:none ne fait RIEN (il n'a pas de boîte de rendu) — le diff --git a/internal/ajean/ui/src/styles.css b/internal/ajean/ui/src/styles.css index 3e4a24c..89dff4a 100644 --- a/internal/ajean/ui/src/styles.css +++ b/internal/ajean/ui/src/styles.css @@ -790,10 +790,12 @@ textarea.sctl{min-height:76px;resize:vertical;line-height:1.5} /* Modale ouverte mais pas encore remplie : on affiche le voile de chargement À LA PLACE du formulaire et du pied. Estomper le formulaire ne suffisait pas — on voyait quand même les champs s'écrire un par un derrière le voile. */ -/* Fond TRANSPARENT : le formulaire est déjà rendu invisible par `visibility`, - un fond opaque ne servirait qu'à masquer aussi le titre de la modale. */ -.modal-load{display:none;position:absolute;inset:0;z-index:2;align-items:center;justify-content:center; - pointer-events:none} +/* Voile OPAQUE, posé sous l'en-tête (le titre reste lisible) : `visibility:hidden` + sur le formulaire suffirait en théorie, mais un fond plein garantit qu'aucun + reste du preset précédent (moteur coché, réglages) ne puisse apparaître une + fraction de seconde. --mh = hauteur mesurée de l'en-tête, posée à l'ouverture. */ +.modal-load{display:none;position:absolute;inset:var(--mh,52px) 0 0 0;z-index:2; + align-items:center;justify-content:center;background:var(--bg);border-radius:0 0 12px 12px} .modal-ov.loading .modal-load{display:flex} /* visibility (et non display) : le formulaire garde sa place, donc la carte a déjà sa taille finale — la révéler ne provoque plus d'à-coup de hauteur. */