diff --git a/containers/libreportal/frontend/core/setup/css/setup-wizard.css b/containers/libreportal/frontend/core/setup/css/setup-wizard.css index d88cea7..746fad9 100755 --- a/containers/libreportal/frontend/core/setup/css/setup-wizard.css +++ b/containers/libreportal/frontend/core/setup/css/setup-wizard.css @@ -1286,6 +1286,14 @@ body.setup-wizard-open { up, so no other overlay's stacking is affected. */ body.setup-wizard-open .eo-modal { z-index: 10000; } +/* And whatever is meant to float ABOVE a modal has to come up with it. + custom-select portals its popup into at z-index 1200 — chosen, as + forms.css says, to clear eo-modal at 1100. Raising the modal to 10000 above + silently broke that: inside the wizard the dropdown opened behind the dialog + that owns it, so a select looked properly enhanced and simply did not + respond. Scoped to the wizard, so no other overlay's stacking moves. */ +body.setup-wizard-open .custom-select-popup { z-index: 10001; } + /* Modal chrome comes from the shared eo-modal (core/overlays). Only the storage-specific CONTENT styles below are ours — they render inside .eo-modal-body. */ diff --git a/scripts/dev/lp-backup-dialog-test b/scripts/dev/lp-backup-dialog-test index 3c9a46a..35aacd0 100755 --- a/scripts/dev/lp-backup-dialog-test +++ b/scripts/dev/lp-backup-dialog-test @@ -60,6 +60,35 @@ read -r -d '' DRIVE <<'JS' out.labelsStyled = !!document.querySelector('.setup-field label'); out.groupsAtOpen = groupsShown(); + // The popup must be REACHABLE, not merely present. custom-select portals it + // into at z-index 1200 — above eo-modal's 1100 — but the wizard raises + // its modal to 10000, which put the popup behind the dialog that owns it. The + // control still reported as enhanced and simply did not respond, so only a + // hit test catches it: what is actually on top at the popup's own centre? + { + const btn = type.closest('.custom-select').querySelector('.custom-select-button'); + btn.click(); + await wait(400); + const popup = document.querySelector('.custom-select-popup'); + out.popupOpens = !!popup; + if (popup) { + const r = popup.getBoundingClientRect(); + const hit = document.elementFromPoint(r.left + r.width / 2, r.top + 12); + out.popupZ = parseInt(getComputedStyle(popup).zIndex, 10); + out.modalZ = parseInt(getComputedStyle(document.querySelector('.eo-modal')).zIndex, 10); + out.popupOnTop = !!(hit && hit.closest('.custom-select-popup')); + out.popupOptions = popup.querySelectorAll('.custom-select-option').length; + + // And picking one has to take effect, the way a person would do it. + const opt = [...popup.querySelectorAll('.custom-select-option')] + .find(o => /SFTP/i.test(o.textContent)); + if (opt) { opt.click(); await wait(400); } + out.pickedValue = type.value; + out.pickedLabel = btn.textContent.trim(); + out.pickedGroups = groupsShown(); + } + } + // Each type shows only its own fields. out.swap = {}; for (const want of ['sftp','s3','b2','local']) { @@ -110,6 +139,15 @@ chk "labels styled" "$(jq -r .labelsStyled <<< "$OUT")" "true" chk "opens on local" "$(jq -r '.groupsAtOpen | join(",")' <<< "$OUT")" "local" chk "add button is styled" "$(jq -r .addButtonStyled <<< "$OUT")" "true" +echo "--- the dropdown is reachable, not just enhanced ---" +chk "popup opens" "$(jq -r .popupOpens <<< "$OUT")" "true" +chk "four options" "$(jq -r .popupOptions <<< "$OUT")" "4" +chk "popup above modal" "$(jq -r 'if .popupZ > .modalZ then "true" else "false" end' <<< "$OUT")" "true" +chk "popup is on top" "$(jq -r .popupOnTop <<< "$OUT")" "true" +chk "picking applies" "$(jq -r .pickedValue <<< "$OUT")" "sftp" +chk "button label" "$(jq -r .pickedLabel <<< "$OUT")" "SFTP" +chk "fields followed" "$(jq -r '.pickedGroups | join(",")' <<< "$OUT")" "sftp" + echo "--- each type shows only its own fields ---" for ty in local sftp s3 b2; do chk "$ty" "$(jq -r --arg t "$ty" '.swap[$t] | join(",")' <<< "$OUT")" "$ty"