diff --git a/app/[locale]/page.tsx b/app/[locale]/page.tsx index a700de1c..31253d06 100644 --- a/app/[locale]/page.tsx +++ b/app/[locale]/page.tsx @@ -2121,25 +2121,44 @@ export default function Home() { )} - {/* Mobile/Tablet Sidebar Overlay Backdrop */} + {/* Mobile/Tablet Sidebar Overlay Backdrop. + When embedded in a Pro pane the viewport is desktop-wide, so the + `lg:hidden` viewport-variant alone wouldn't gate this overlay; + scope to the pane via `absolute` so the backdrop stays inside + the pane instead of covering the whole window. */} {(isMobile || isTablet) && sidebarOpen && !inlineApp && (
setSidebarOpen(false)} /> )} - {/* Sidebar - overlay on mobile/tablet, fixed on desktop */} + {/* Sidebar - overlay on mobile/tablet, in-flow on desktop. + When embedded, overlay-mode is driven by pane-aware JS rather + than viewport-variants (which still see the full window). */}
(null); + // Measured pane width, published to children via PaneSizeContext so that + // useDeviceDetection / useIsMobile / etc. branch on pane width — not full + // viewport — and inner pages collapse to their mobile/tablet layouts when + // the pane is narrow. + const [paneWidth, setPaneWidth] = useState(null); + + useEffect(() => { + const el = paneRef.current; + if (!el || typeof ResizeObserver === "undefined") return; + const initialRect = el.getBoundingClientRect(); + if (initialRect.width > 0) setPaneWidth(initialRect.width); + const ro = new ResizeObserver((entries) => { + const entry = entries[0]; + if (!entry) return; + const w = entry.contentRect.width; + setPaneWidth((prev) => (prev !== null && Math.abs(prev - w) < 0.5 ? prev : w)); + }); + ro.observe(el); + return () => ro.disconnect(); + }, []); + return (
{ if (!isFocused) onPaneFocus(paneId); }} > - {tabs - .filter((tab) => loadedTabIds.includes(tab.id)) - .map((tab) => { - const isActive = tab.id === activeTabId; - return ( -
- {renderTabBody(tab)} -
- ); - })} + + {tabs + .filter((tab) => loadedTabIds.includes(tab.id)) + .map((tab) => { + const isActive = tab.id === activeTabId; + return ( +
+ {renderTabBody(tab)} +
+ ); + })} +
); } @@ -233,8 +259,16 @@ export default function ProHome() { if (!isDesktop) return null; + // Stable keys are essential: when the split collapses, the row's child + // list goes from [splitPane, divider, mainPane] (or the leading variant) + // to [mainPane]. Without keys, React would reuse the Pane instance at + // index 0 — repurposing the *split* pane's instance into the main pane, + // which strands the main pane's ResizeObserver/paneWidth on a now- + // unmounted DOM node and reparents the mail tab body (causing remount + // + stale "still-narrow" measurements after the split is closed). const mainPane = (