42176e8b1f29

broaden modal detection to form ancestor + position:fixed fallback (v3.6.132)

time
2026-05-29 17:10 UTC · 5 months ago
machine
koh2
parent
91ca0c3fee4e
4 files manifest.firefox.json+1 −1manifest.json+1 −1package.json+1 −1src/content/inject.ts+23 −7
manifest.firefox.json+1 −1
@@ -2,7 +2,7 @@22   "_comment_audio_capture": "Firefox does not honor the Chrome 'audioCapture' optional_permission — getUserMedia in WebExtensions is gated solely by the runtime permission prompt. Microphone access for chirp pairing works from the popup under the existing '<all_urls>' host permission; no manifest entry is required or accepted here.",33   "manifest_version": 3,44   "name": "Peach Password Manager",5-  "version": "3.6.131",5+  "version": "3.6.132",66   "description": "Zero-knowledge password manager",77   "browser_specific_settings": {88     "gecko": {

view file

manifest.json+1 −1
@@ -1,7 +1,7 @@11 {22   "manifest_version": 3,33   "name": "Peach Password Manager",4-  "version": "3.6.131",4+  "version": "3.6.132",55   "description": "Zero-knowledge password manager",66   "action": {77     "default_popup": "src/popup/index.html",

view file

package.json+1 −1
@@ -1,6 +1,6 @@11 {22   "name": "peach",3-  "version": "3.6.131",3+  "version": "3.6.132",44   "description": "Zero-knowledge password manager",55   "type": "module",66   "scripts": {

view file

src/content/inject.ts+23 −7
@@ -1253,14 +1253,30 @@12531253   options: SelectorOptions = {}12541254 ): () => void {12551255   const host = document.createElement("div");1256-  // When anchorEl is inside a focus-trapping modal (aria-modal, role=dialog, <dialog>),1257-  // the modal's JS focus trap fires when Peach's internal inputs gain focus (they are1258-  // outside the modal in the DOM), immediately blurring them and closing the identity1259-  // suggest list. Fix: detect the modal ancestor and append the host inside it so focus1256+  // When anchorEl is inside a focus-trapping modal the modal's JS focus trap fires1257+  // when Peach's internal inputs gain focus (they are outside the modal's DOM subtree),1258+  // immediately blurring them and closing the identity suggest list.1259+  // Fix: detect the containing form or modal and append the host INSIDE it so focus12601260   // traps see Peach as within the modal. Use position:fixed so the popup positions1261-  // correctly relative to the viewport — overflow and transforms on the modal cannot1262-  // clip or misplace a fixed child.1263-  const modalAncestor = anchorEl.closest<HTMLElement>('dialog, [aria-modal="true"], [role="dialog"]');1261+  // correctly relative to the viewport regardless of the container's CSS context —1262+  // overflow:hidden and most transforms do not affect fixed children.1263+  //1264+  // Detection priority:1265+  //   1. <form> ancestor — always inside any focus-trap container wrapping the form1266+  //   2. ARIA modal (dialog / aria-modal / role=dialog)1267+  //   3. position:fixed ancestor — catches modals that omit ARIA attributes1268+  const modalAncestor = (1269+    anchorEl.closest<HTMLElement>('form') ??1270+    anchorEl.closest<HTMLElement>('dialog, [aria-modal="true"], [role="dialog"]') ??1271+    (() => {1272+      let cur: HTMLElement | null = anchorEl.parentElement;1273+      while (cur && cur !== document.body) {1274+        if (window.getComputedStyle(cur).position === 'fixed') return cur;1275+        cur = cur.parentElement;1276+      }1277+      return null;1278+    })()1279+  );12641280   host.style.cssText = `position: ${modalAncestor ? "fixed" : "absolute"}; z-index: 2147483647;`;12651281   host.style.setProperty("--peach-accent", accentHex);12661282   host.style.setProperty("--peach-accent-dim", withAlpha(accentHex, "28"));

view file