From 590b49a3e556df297686e73bb4930ae4f050a517 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 28 Feb 2026 00:56:40 +0000 Subject: [PATCH 1/2] Anchor control panel and track list panel to visible bounds Previously, ControlPanel and TrackListPanel were positioned using the static layoutBounds, so they would not follow the visible screen edge when the browser window was larger than the default layout size. Move controlPanel positioning into the visibleBoundsProperty.link() callback alongside all other edge-anchored elements, using visibleBounds.minX and visibleBounds.minY. Because TrackListPanel already re-positions itself reactively via controlPanel.boundsProperty, it inherits the correct position automatically. Also fix the initialPanelPos computation: since controlPanel.left is now set inside the deferred link callback, reading controlPanel.right before that fires would yield a stale value, so compute the x offset directly from layoutBounds + CONTROL_PANEL_LEFT_MARGIN + controlPanel.width. https://claude.ai/code/session_01Uvtq2RdaEMJbfUV3ER2GMh --- src/screen-name/view/SimScreenView.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/screen-name/view/SimScreenView.ts b/src/screen-name/view/SimScreenView.ts index 2c77371..8e91a2e 100644 --- a/src/screen-name/view/SimScreenView.ts +++ b/src/screen-name/view/SimScreenView.ts @@ -71,8 +71,6 @@ export class SimScreenView extends ScreenView { // ── Control panel / tool checkboxes (upper left) ─────────────────────── const controlPanel = new ControlPanel(model.overlayTools, trackLabPreferences); - controlPanel.left = this.layoutBounds.left + CONTROL_PANEL_LEFT_MARGIN; - controlPanel.top = this.layoutBounds.top + SCREEN_TOP_MARGIN; this.addChild(controlPanel); // ── Track list panel (beneath control panel) ───────────────────────── @@ -93,8 +91,11 @@ export class SimScreenView extends ScreenView { // ── Initial video panel position ────────────────────────────────────── // Compute the initial position based on layout and write it into the model // so it persists (and can be restored on Reset All). + // NOTE: controlPanel.left is set inside visibleBoundsProperty.link(), which + // fires after this code runs, so we compute the x position from layoutBounds + // directly rather than from controlPanel.right to avoid a stale value. const initialPanelPos = new Vector2( - controlPanel.right + VIDEO_PLAYER_LEFT_SPACING, + this.layoutBounds.left + CONTROL_PANEL_LEFT_MARGIN + controlPanel.width + VIDEO_PLAYER_LEFT_SPACING, this.layoutBounds.top + SCREEN_TOP_MARGIN, ); model.playback.panelPositionProperty.value = initialPanelPos; @@ -232,6 +233,10 @@ export class SimScreenView extends ScreenView { // is wider/taller than the default layout. All right-edge anchors are linked // here so they track the actual visible edge rather than the fixed layoutBounds. this.visibleBoundsProperty.link((visibleBounds) => { + // Control panel: anchor to the actual visible top-left corner. + controlPanel.left = visibleBounds.minX + CONTROL_PANEL_LEFT_MARGIN; + controlPanel.top = visibleBounds.minY + SCREEN_TOP_MARGIN; + // Reset button: anchor to the actual visible bottom-right corner. resetAllButton.right = visibleBounds.maxX - RESET_BUTTON_MARGIN; resetAllButton.bottom = visibleBounds.maxY - RESET_BUTTON_MARGIN; From 468a1605005a6c0d32bd999b4d03de206101b201 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 28 Feb 2026 00:59:57 +0000 Subject: [PATCH 2/2] Anchor video player top to visible bounds edge The video player node's vertical position is now driven by visibleBoundsProperty.link() (using visibleBounds.minY + SCREEN_TOP_MARGIN), matching the strategy already used for the control panel and track list panel. This ensures the video always hugs the visible top edge when the browser window is taller than the default layout bounds. The panelPositionProperty link now only sets the horizontal (left) position, since the top is fully managed by the visible-bounds listener. https://claude.ai/code/session_01Uvtq2RdaEMJbfUV3ER2GMh --- src/screen-name/view/SimScreenView.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/screen-name/view/SimScreenView.ts b/src/screen-name/view/SimScreenView.ts index 8e91a2e..f23e7bb 100644 --- a/src/screen-name/view/SimScreenView.ts +++ b/src/screen-name/view/SimScreenView.ts @@ -100,12 +100,11 @@ export class SimScreenView extends ScreenView { ); model.playback.panelPositionProperty.value = initialPanelPos; - // ── Link panelPositionProperty → videoPlayerNode position ──────────── - // Use left/top (not translation) so pos represents the top-left of the - // *entire* node — header frame included — not just the video content origin. + // ── Link panelPositionProperty → videoPlayerNode horizontal position ─ + // Only the x (left) is driven here; the top is anchored to visibleBounds + // inside visibleBoundsProperty.link() so it always tracks the visible edge. model.playback.panelPositionProperty.link((pos) => { this.videoPlayerNode.left = pos.x; - this.videoPlayerNode.top = pos.y; }); // ── Panel move drag (on the header bar) ─────────────────────────────── @@ -237,6 +236,9 @@ export class SimScreenView extends ScreenView { controlPanel.left = visibleBounds.minX + CONTROL_PANEL_LEFT_MARGIN; controlPanel.top = visibleBounds.minY + SCREEN_TOP_MARGIN; + // Video player: top tracks the visible top edge; left is driven by panelPositionProperty. + this.videoPlayerNode.top = visibleBounds.minY + SCREEN_TOP_MARGIN; + // Reset button: anchor to the actual visible bottom-right corner. resetAllButton.right = visibleBounds.maxX - RESET_BUTTON_MARGIN; resetAllButton.bottom = visibleBounds.maxY - RESET_BUTTON_MARGIN;