5cf135768dc8

restore flow: detached window for file pickers, tab font 11px to fit 320px popup

time
2026-05-01 13:28 UTC · 5 months ago
machine
koh2
parent
101ea06cc166
2 files src/popup/styles/popup.css+4 −2src/popup/views/Lock.tsx+24 −3
src/popup/styles/popup.css+4 −2
@@ -3626,16 +3626,18 @@36263626   background: none;36273627   border: none;36283628   cursor: pointer;3629-  padding: 3px 4px;3629+  padding: 3px 2px;36303630   font-family: 'Cormorant Garamond', Georgia, serif;36313631   font-style: italic;3632-  font-size: 13px;3632+  font-size: 11px;36333633   color: var(--peach-t2);36343634   transition: color 150ms ease, text-shadow 150ms ease;36353635   flex: 1;3636+  min-width: 0;36363637   text-align: center;36373638   white-space: nowrap;36383639   overflow: hidden;3640+  text-overflow: ellipsis;36393641 }36403642 .peach-restore-tab:hover {36413643   color: var(--peach-accent);

view file

src/popup/views/Lock.tsx+24 −3
@@ -39,7 +39,11 @@3939   const [confirmPassword, setConfirmPassword] = createSignal("");4040   const [error, setError] = createSignal("");4141   const [loading, setLoading] = createSignal(false);42-  const [restoreSurface, setRestoreSurface] = createSignal<RestoreSurface>(null);42+  // If the popup was reopened as a detached window for file picking, go straight43+  // to the restore view so the user lands where they intended.44+  const [restoreSurface, setRestoreSurface] = createSignal<RestoreSurface>(45+    new URLSearchParams(location.search).has("detached") ? "restore" : null46+  );4347   const [showPassword, setShowPassword] = createSignal(false);4448 4549   const MIN_LENGTH = 12;@@ -140,11 +144,28 @@140144     setLoading(false);141145   }142146 143-  function openRestore(surface: Exclude<RestoreSurface, null>) {147+  async function openRestore(surface: Exclude<RestoreSurface, null>) {144148     if (!props.ready || loading()) return;145149     setPassword("");146150     setConfirmPassword("");147151     setError("");152+153+    // The toolbar popup closes when a native file dialog steals focus (macOS).154+    // Reopen as a detached chrome.windows.create popup, which survives focus155+    // loss. The detached window initialises directly into the restore view via156+    // the ?detached URL param.157+    const isDetached = new URLSearchParams(location.search).has("detached");158+    if (!isDetached) {159+      try {160+        const url = chrome.runtime.getURL("src/popup/index.html") + "?detached=1";161+        await chrome.windows.create({ url, type: "popup", width: 340, height: 560, focused: true });162+        window.close();163+        return;164+      } catch {165+        // Not in extension context (dev mode) — fall through to direct open.166+      }167+    }168+148169     setRestoreSurface(surface);149170   }150171 @@ -371,7 +392,7 @@371392             <p class="peach-hint">Already have a backup?</p>372393             <button373394               class="peach-lock-restore-link"374-              onClick={() => openRestore("restore")}395+              onClick={() => void openRestore("restore")}375396               disabled={!props.ready}376397             >377398               › restore from backup

view file