feat: narrow-window behavior — sidebar auto-close, chrome wrap, 640px floor
The sidebar no longer squeezes the page when the window narrows; the page itself never goes below a comfortable floor (owner decisions, 2026-09-17: 640px min, widen-window on toggle, auto-restore): - minWidth 640 / minHeight 600 on the BrowserWindow (macOS enforces) - Below SIDEBAR_AUTOCLOSE (928 = 640 + 288 sidebar) the sidebar auto-closes, and auto-RESTORES when the window widens past it again — both fall out of one expression: rendered = pref && !narrow, where pref is the persisted user choice. Manual closes persist and stay closed; auto-close never touches the preference. - Opening the sidebar while narrow asks the shell to widen the window to 928 first (new lh:expand-window IPC, preload.cjs contextBridge — the renderer's first and only Electron bridge): the toggle is never a dead button, and the layout never has to survive narrow + sidebar. In the plain browser there is no suppression and no widening — a narrow tab opens the sidebar if the user says so. - Graph chrome row wraps: max-w-[calc(100%-9rem)] + flex-wrap keeps the row clear of the header toggle cluster and stacks it onto extra lines below ~640px instead of overflowing left. State machine verified in the Electron dev shell across all six transitions (auto-close, auto-restore, manual-close-persists, reopen-widens, browser fallback, wrap at 640/500/360).
This commit is contained in:
+27
-1
@@ -21,13 +21,17 @@
|
||||
* settings milestone builds the UI.
|
||||
*/
|
||||
|
||||
const { app, BrowserWindow, Menu, session, shell } = require("electron");
|
||||
const { app, BrowserWindow, Menu, ipcMain, session, shell } = require("electron");
|
||||
const { spawn } = require("node:child_process");
|
||||
const fs = require("node:fs");
|
||||
const http = require("node:http");
|
||||
const net = require("node:net");
|
||||
const path = require("node:path");
|
||||
|
||||
// Mirrors SIDEBAR_AUTOCLOSE in components/sidebar.tsx — keep in sync (the
|
||||
// renderer owns the number; this is the IPC widen target).
|
||||
const SIDEBAR_AUTOCLOSE = 928;
|
||||
|
||||
const PRODUCT_NAME = "LearnHarness";
|
||||
const AUTH_FILE = () => path.join(app.getPath("userData"), "auth.json");
|
||||
const DATA_DIR = () => path.join(app.getPath("userData"), "data");
|
||||
@@ -199,6 +203,7 @@ function createWindow(url) {
|
||||
contextIsolation: true,
|
||||
sandbox: true,
|
||||
nodeIntegration: false,
|
||||
preload: path.join(__dirname, "preload.cjs"),
|
||||
},
|
||||
// Live-resize + first-paint flash (owner, 2026-09-17): during a resize
|
||||
// the native window surface changes size before Chromium's compositor
|
||||
@@ -209,6 +214,14 @@ function createWindow(url) {
|
||||
// appears only once the page has actually rendered.
|
||||
backgroundColor: "#141414",
|
||||
show: false,
|
||||
// Narrow-window behavior (owner, 2026-09-17): 640px is the floor —
|
||||
// below it even a wrapped chrome row gets cramped and the chat header
|
||||
// (lights gutter 92 + toggle + title) runs out of room. The sidebar
|
||||
// auto-closes below 928 = 640 + 288 (sidebar) in the renderer
|
||||
// (components/sidebar.tsx, SIDEBAR_AUTOCLOSE); its "lh:expand-window"
|
||||
// IPC widens the window back to that threshold.
|
||||
minWidth: 640,
|
||||
minHeight: 600,
|
||||
});
|
||||
|
||||
const allowedOrigin = () => new URL(url).origin;
|
||||
@@ -293,6 +306,19 @@ async function main() {
|
||||
}
|
||||
|
||||
installMenu();
|
||||
|
||||
// Sidebar-at-narrow-window (owner, 2026-09-17): the renderer auto-closes
|
||||
// the sidebar below SIDEBAR_AUTOCLOSE (928px); opening it again at that
|
||||
// width asks the window to widen instead — the layout never has to
|
||||
// accommodate a narrow window + open sidebar. Top-left stays fixed, the
|
||||
// window grows right. No-op when already wide.
|
||||
ipcMain.on("lh:expand-window", (event) => {
|
||||
const win = BrowserWindow.fromWebContents(event.sender);
|
||||
if (!win) return;
|
||||
const { x, y, width, height } = win.getBounds();
|
||||
const target = SIDEBAR_AUTOCLOSE;
|
||||
if (width < target) win.setBounds({ x, y, width: target, height });
|
||||
});
|
||||
app.on("activate", () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) createWindow(url);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user