1a849508944a

two-pane: layoutClass signal, isTwoPaneLayout helper; list overlay scopes to 320px sidebar on medium+, 360px on expanded; selecting entry keeps list mounted

time
2026-05-01 04:10 UTC · 5 months ago
machine
koh2
parent
bd35b3ff296d
2 files src/popup/App.tsx+10 −5src/popup/styles/popup.css+39 −0
src/popup/App.tsx+10 −5
@@ -129,6 +129,8 @@129129     "enter"130130   );131131   const [contentTransitioning, setContentTransitioning] = createSignal(false);132+  const [layoutClass, setLayoutClass] = createSignal<"compact" | "medium" | "expanded">("compact");133+  const isTwoPaneLayout = () => layoutClass() === "medium" || layoutClass() === "expanded";132134   const [hasVault, setHasVault] = createSignal(false);133135   const [onboarded, setOnboarded] = createSignal(true);134136   const [entries, setEntries] = createSignal<VaultEntry[]>([]);@@ -373,9 +375,10 @@373375         const w = window.innerWidth;374376         const cls = document.body.classList;375377         cls.remove("layout-compact", "layout-medium", "layout-expanded");376-        if (w >= 840) cls.add("layout-expanded");377-        else if (w >= 600) cls.add("layout-medium");378-        else cls.add("layout-compact");378+        const next: "compact" | "medium" | "expanded" =379+          w >= 840 ? "expanded" : w >= 600 ? "medium" : "compact";380+        cls.add(`layout-${next}`);381+        setLayoutClass(next);379382       };380383       updateLayoutClass();381384       window.addEventListener("resize", updateLayoutClass);@@ -885,7 +888,7 @@885888     setContentTransitioning(false);886889     setContentPhase("enter");887890     queueContentIdle();888-    if (!skipViewSet) setView("entry");891+    if (!skipViewSet) setView(isTwoPaneLayout() ? "list" : "entry");889892   }890893 891894   async function handleUnlock() {@@ -909,7 +912,9 @@909912     setContentTransitioning(false);910913     setContentPhase("enter");911914     queueContentIdle();912-    setView("entry");915+    // Two-pane layouts (Z Fold inner display, tablets, DeX) keep the list916+    // mounted on the left and only update the detail pane on selection.917+    if (!isTwoPaneLayout()) setView("entry");913918   }914919 915920   function handleAdd() {

view file

src/popup/styles/popup.css+39 −0
@@ -7104,3 +7104,42 @@71047104     padding-right: 8px;71057105   }71067106 }7107+7108+/* ── Two-pane on medium+ ───────────────────────────────────────────────7109+   The vault list is normally a full-screen overlay. On Z Fold inner /7110+   tablet / DeX widths, scope it to a 320px left column so the entry7111+   detail behind it stays visible on the right. handleSelectEntry keeps7112+   view===\"list\" on these widths so the list never animates away. */7113+body.peach-mobile.layout-medium .peach-overlay-view,7114+body.peach-mobile.layout-expanded .peach-overlay-view {7115+  right: auto;7116+  width: 320px;7117+  border-right: 1px solid var(--peach-t3);7118+  animation: none;7119+  z-index: 2;7120+}7121+7122+/* Push the entry-frame content past the sidebar so it isn't hidden. */7123+body.peach-mobile.layout-medium .peach-content-frame,7124+body.peach-mobile.layout-expanded .peach-content-frame {7125+  padding-left: 320px;7126+}7127+7128+/* Search bar is part of the shell — when the list sidebar is mounted on7129+   medium+, the list owns search. Keep the shell search bar visible only7130+   when no overlay is active. */7131+body.peach-mobile.layout-medium .peach-search-wrap,7132+body.peach-mobile.layout-expanded .peach-search-wrap {7133+  padding-left: 320px;7134+}7135+7136+/* On expanded (840+), leave more breathing room and cap detail width. */7137+body.peach-mobile.layout-expanded .peach-content-frame {7138+  padding-left: 360px;7139+}7140+body.peach-mobile.layout-expanded .peach-overlay-view {7141+  width: 360px;7142+}7143+body.peach-mobile.layout-expanded .peach-search-wrap {7144+  padding-left: 360px;7145+}

view file