From 3301b764f70cc953f5806b9ad535b5f405dc0b1b Mon Sep 17 00:00:00 2001 From: Yvv Date: Tue, 11 Aug 2026 20:11:54 +0200 Subject: [PATCH] =?UTF-8?q?v2=20:=20correctifs=20QA=20=E2=80=94=20overlays?= =?UTF-8?q?=20pos=C3=A9s,=20accueil=20jamais=20orphelin,=20finitions=20mob?= =?UTF-8?q?iles?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - overlays Nuxt UI (UModal/USlideover) : géométrie posée en CSS (assets/css/overlays.css) — les utilitaires tailwind attendus par @nuxt/ui ne sont pas générés (UnoCSS ne scanne pas node_modules) : drawer mobile et modales de confirmation se rendaient hors écran - a11y : title/description sur les 3 overlays (DialogTitle/Description rendus, warnings reka-ui éteints), fermeture du drawer ancrée et testée - suppression du collectif actif : bascule sur un collectif restant — jamais d'accueil orphelin (test store ajouté, 343 vitest verts) - observatoire : la route « transmis » entre dans les barres (base 100 %) - overflows mobiles à zéro : formules KaTeX (défilement), table vigueur (défilement < 768px), pill cible (retour à la ligne), inputs decider et mandat (border-box) - vérifié navigateur : drawer, modale, 14 routes sans débordement, zéro erreur console Co-Authored-By: Claude Fable 5 --- frontend/app/assets/css/overlays.css | 147 ++++++++++++++++++ .../components/decisions/DecisionVigor.vue | 4 + .../onboarding/DataCollectivesCard.vue | 6 +- .../components/texts/AtelierFormulaLab.vue | 2 +- .../app/components/votes/VoteInstruct.vue | 2 +- .../app/components/votes/VoteParametric.vue | 9 +- frontend/app/layouts/default.vue | 3 +- frontend/app/lexicon.ts | 1 + frontend/app/pages/decider.vue | 1 + frontend/app/pages/decisions/observatoire.vue | 2 +- frontend/app/pages/mandats/nouveau.vue | 2 +- frontend/app/stores/collective.ts | 4 + frontend/nuxt.config.ts | 2 +- frontend/tests/stores/decisions.spec.ts | 18 +++ 14 files changed, 194 insertions(+), 9 deletions(-) create mode 100644 frontend/app/assets/css/overlays.css diff --git a/frontend/app/assets/css/overlays.css b/frontend/app/assets/css/overlays.css new file mode 100644 index 0000000..89efb9a --- /dev/null +++ b/frontend/app/assets/css/overlays.css @@ -0,0 +1,147 @@ +/* + * Overlays Nuxt UI (UModal / USlideover) — géométrie posée à la main. + * Les composants @nuxt/ui portent des classes utilitaires tailwind que ce + * projet ne génère pas (UnoCSS ne scanne pas node_modules) : sans ces règles, + * voile et panneaux se rendent à leur position statique, en fin de , + * donc hors écran. On cible la structure stable posée par reka-ui. + */ + +/* Voile */ +body > div.fixed.inset-0[data-state] { + position: fixed; + inset: 0; + z-index: 90; + background: rgb(15 20 25 / 0.45); + backdrop-filter: blur(2px); +} +body > div.fixed.inset-0[data-state='open'] { + animation: ldov-fade-in 0.15s ease; +} + +/* Panneau latéral (USlideover — drawer mobile) */ +body > [role='dialog'][data-side] { + position: fixed; + top: 0; + bottom: 0; + width: min(20rem, 86vw); + z-index: 91; + display: flex; + flex-direction: column; + overflow-y: auto; + background: var(--mood-surface); + color: var(--mood-text); + box-shadow: 0 12px 40px rgb(0 0 0 / 0.3); +} +body > [role='dialog'][data-side='left'] { + left: 0; + right: auto; + border-radius: 0 16px 16px 0; +} +body > [role='dialog'][data-side='right'] { + right: 0; + left: auto; + border-radius: 16px 0 0 16px; +} +body > [role='dialog'][data-side='left'][data-state='open'] { + animation: ldov-slide-left 0.18s ease; +} +body > [role='dialog'][data-side='right'][data-state='open'] { + animation: ldov-slide-right 0.18s ease; +} + +/* Modale centrée (UModal) */ +body > [role='dialog']:not([data-side]) { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: min(26rem, calc(100vw - 2rem)); + max-height: calc(100dvh - 2rem); + overflow-y: auto; + z-index: 91; + background: var(--mood-surface); + color: var(--mood-text); + border-radius: 16px; + box-shadow: 0 18px 50px rgb(0 0 0 / 0.28); +} +body > [role='dialog']:not([data-side])[data-state='open'] { + animation: ldov-pop 0.15s ease; +} + +/* Blocs internes générés par Nuxt UI — classes posées via la prop :ui */ +.ldov-header { + position: relative; + display: flex; + align-items: center; + justify-content: space-between; + gap: 0.75rem; + padding: 1rem 3.5rem 0.5rem 1.25rem; +} +.ldov-title { + margin: 0; + font-size: 1.0625rem; + font-weight: 800; + color: var(--mood-text); +} +/* description a11y sans rendu visuel (lecteurs d'écran seulement) */ +.ldov-sr-only { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip-path: inset(50%); + white-space: nowrap; +} +.ldov-desc { + margin: 0; + padding: 0 1.25rem; + font-size: 0.875rem; + color: var(--mood-text-muted); +} +.ldov-body { + flex: 1; + display: flex; + flex-direction: column; + gap: 1rem; + padding: 0.5rem 1.25rem 1.25rem; +} +.ldov-close { + position: absolute; + top: 0.75rem; + right: 0.75rem; + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 2.25rem; + min-height: 2.25rem; + border-radius: 14px; + background: var(--mood-input-bg); + color: var(--mood-text); + cursor: pointer; + transition: background 0.1s ease, transform 0.1s ease; +} +.ldov-close:hover { + background: var(--mood-accent-soft); + transform: translateY(-1px); +} +.ldov-close:active { + transform: translateY(0); +} + +@keyframes ldov-fade-in { + from { opacity: 0; } +} +@keyframes ldov-slide-left { + from { transform: translateX(-100%); } +} +@keyframes ldov-slide-right { + from { transform: translateX(100%); } +} +@keyframes ldov-pop { + from { + opacity: 0; + transform: translate(-50%, -50%) scale(0.96); + } +} diff --git a/frontend/app/components/decisions/DecisionVigor.vue b/frontend/app/components/decisions/DecisionVigor.vue index 5f4cedd..6a16a9c 100644 --- a/frontend/app/components/decisions/DecisionVigor.vue +++ b/frontend/app/components/decisions/DecisionVigor.vue @@ -219,6 +219,10 @@ function saveMeasure(index: number) { border-collapse: collapse; font-size: 0.875rem; } +@media (max-width: 768px) { + /* la table ne sait pas rétrécir sous la largeur de son contenu : elle défile */ + .vig__table { display: block; overflow-x: auto; } +} .vig__table th { text-align: left; font-size: 0.8125rem; diff --git a/frontend/app/components/onboarding/DataCollectivesCard.vue b/frontend/app/components/onboarding/DataCollectivesCard.vue index 4d13118..2fb9b23 100644 --- a/frontend/app/components/onboarding/DataCollectivesCard.vue +++ b/frontend/app/components/onboarding/DataCollectivesCard.vue @@ -91,7 +91,11 @@ async function removeConfirmed() { - +