From a0f74ae827223acf6f638d549c6ce1c801fb0270 Mon Sep 17 00:00:00 2001 From: Andrew Mikofalvy <5668128+amikofalvy@users.noreply.github.com> Date: Thu, 25 Jun 2026 11:38:34 -0700 Subject: [PATCH] Open terminal dock at ~1/3 of window height on first use (#2113) * Open terminal dock at ~1/3 of window height on first use The integrated terminal opened at a fixed 240px, too short to read a command's output without dragging the divider. Compute the first-open height as ~1/3 of the editor viewport instead, so it scales with window size while still respecting the 120px floor and 50vh ceiling. A height set by dragging is still remembered. * Address local review feedback on terminal dock height - Pin the ~1/3 default with a literal (333) instead of a fraction-derived value so a regression to the fraction is actually caught; add a short-viewport case covering the new fraction-below-floor composition. - Make DEFAULT_TERMINAL_HEIGHT_FRACTION module-private (was exported only for the test). - Correct header comments: the fixed-px fallback is for no-window hosts, not storage-restricted ones (those hit the catch); the default scales with the renderer window, not the editor pane. Document the catch's intentional fixed-px fallback. GitOrigin-RevId: c1ee22f14f2f5a321964c2b2f64063ffe4be8881 --- .changeset/terminal-dock-default-height.md | 5 ++++ .../app/src/lib/terminal-height-store.test.ts | 23 +++++++++++++++---- packages/app/src/lib/terminal-height-store.ts | 13 ++++++++--- 3 files changed, 34 insertions(+), 7 deletions(-) create mode 100644 .changeset/terminal-dock-default-height.md diff --git a/.changeset/terminal-dock-default-height.md b/.changeset/terminal-dock-default-height.md new file mode 100644 index 000000000..9bdbc46fd --- /dev/null +++ b/.changeset/terminal-dock-default-height.md @@ -0,0 +1,5 @@ +--- +"@inkeep/open-knowledge-app": patch +--- + +The integrated terminal now opens at about one third of the window height on first use, instead of a fixed 240px that was often too short to read a command's output without dragging the divider. The default is computed as a fraction of the window height (so it scales with window size) and still respects the existing 120px floor and 50vh ceiling. A height you set by dragging is remembered as before. diff --git a/packages/app/src/lib/terminal-height-store.test.ts b/packages/app/src/lib/terminal-height-store.test.ts index 961db3f81..ccfd56982 100644 --- a/packages/app/src/lib/terminal-height-store.test.ts +++ b/packages/app/src/lib/terminal-height-store.test.ts @@ -21,10 +21,15 @@ function memoryStorage(initial: Record = {}): HeightStorage { } const TALL = 1000; +const TALL_DEFAULT = 333; describe('readTerminalHeight', () => { - test('absent key returns default', () => { - expect(readTerminalHeight(memoryStorage(), TALL)).toBe(DEFAULT_TERMINAL_HEIGHT); + test('absent key returns the ~1/3-viewport default (1000 → 333)', () => { + expect(readTerminalHeight(memoryStorage(), TALL)).toBe(TALL_DEFAULT); + }); + + test('default below the floor on a short viewport clamps up to MIN (300 → 100 → 120)', () => { + expect(readTerminalHeight(memoryStorage(), 300)).toBe(MIN_TERMINAL_HEIGHT); }); test('valid stored height is returned', () => { @@ -50,18 +55,28 @@ describe('readTerminalHeight', () => { test('non-numeric value falls back to default', () => { const s = memoryStorage({ [TERMINAL_HEIGHT_KEY]: 'not a number' }); - expect(readTerminalHeight(s, TALL)).toBe(DEFAULT_TERMINAL_HEIGHT); + expect(readTerminalHeight(s, TALL)).toBe(TALL_DEFAULT); }); test('empty string falls back to default', () => { const s = memoryStorage({ [TERMINAL_HEIGHT_KEY]: '' }); - expect(readTerminalHeight(s, TALL)).toBe(DEFAULT_TERMINAL_HEIGHT); + expect(readTerminalHeight(s, TALL)).toBe(TALL_DEFAULT); }); test('floating-point value is rounded', () => { const s = memoryStorage({ [TERMINAL_HEIGHT_KEY]: '240.6' }); expect(readTerminalHeight(s, TALL)).toBe(240); }); + + test('throwing storage falls back to the fixed pixel default', () => { + const throwing: HeightStorage = { + getItem() { + throw new Error('SecurityError'); + }, + setItem() {}, + }; + expect(readTerminalHeight(throwing, TALL)).toBe(DEFAULT_TERMINAL_HEIGHT); + }); }); describe('writeTerminalHeight', () => { diff --git a/packages/app/src/lib/terminal-height-store.ts b/packages/app/src/lib/terminal-height-store.ts index 71ffe5316..4cb5f1acc 100644 --- a/packages/app/src/lib/terminal-height-store.ts +++ b/packages/app/src/lib/terminal-height-store.ts @@ -2,6 +2,7 @@ export const TERMINAL_HEIGHT_KEY = 'ok-terminal-height-v1'; export const DEFAULT_TERMINAL_HEIGHT = 240; export const MIN_TERMINAL_HEIGHT = 120; +const DEFAULT_TERMINAL_HEIGHT_FRACTION = 1 / 3; const MAX_TERMINAL_HEIGHT_FRACTION = 0.5; export interface HeightStorage { @@ -14,9 +15,15 @@ function maxHeight(viewportHeight: number): number { return Math.max(MIN_TERMINAL_HEIGHT, Math.round(vh * MAX_TERMINAL_HEIGHT_FRACTION)); } +function defaultHeight(viewportHeight: number): number { + const vh = Number.isFinite(viewportHeight) ? viewportHeight : 0; + if (vh <= 0) return DEFAULT_TERMINAL_HEIGHT; + return Math.round(vh * DEFAULT_TERMINAL_HEIGHT_FRACTION); +} + function clamp(px: number, viewportHeight: number): number { const max = maxHeight(viewportHeight); - if (!Number.isFinite(px)) return Math.min(DEFAULT_TERMINAL_HEIGHT, max); + if (!Number.isFinite(px)) return Math.min(defaultHeight(viewportHeight), max); if (px < MIN_TERMINAL_HEIGHT) return MIN_TERMINAL_HEIGHT; if (px > max) return max; return Math.round(px); @@ -32,9 +39,9 @@ export function readTerminalHeight(storage?: HeightStorage, viewportHeight?: num const s = storage ?? localStorage; const vh = viewportHeight ?? currentViewportHeight(); const raw = s.getItem(TERMINAL_HEIGHT_KEY); - if (raw == null) return clamp(DEFAULT_TERMINAL_HEIGHT, vh); + if (raw == null) return clamp(defaultHeight(vh), vh); const parsed = Number.parseInt(raw, 10); - if (!Number.isFinite(parsed)) return clamp(DEFAULT_TERMINAL_HEIGHT, vh); + if (!Number.isFinite(parsed)) return clamp(defaultHeight(vh), vh); return clamp(parsed, vh); } catch { return DEFAULT_TERMINAL_HEIGHT;