fix: preserve scroll position when toggling Ralph Wiggum panel

- Save xterm viewport scroll position before toggle
- Restore scroll position after panel expand/collapse
- Refit terminal to new container size after layout change
- Add overflow-anchor: none to prevent browser scroll anchoring

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
arkon
2026-01-20 17:24:42 +01:00
co-authored by Claude Opus 4.5
parent 69eada0632
commit eda7c0fd6c
2 changed files with 20 additions and 25 deletions
+19 -8
View File
@@ -265,12 +265,14 @@ class ClaudemanApp {
const data = JSON.parse(e.data);
this.sessions.delete(data.id);
this.terminalBuffers.delete(data.id);
this.innerStates.delete(data.id); // Clean up inner state for this session
if (this.activeSessionId === data.id) {
this.activeSessionId = null;
this.terminal.clear();
this.showWelcome();
}
this.renderSessionTabs();
this.renderInnerStatePanel(); // Update inner panel after session deleted
});
this.eventSource.addEventListener('session:terminal', (e) => {
@@ -718,6 +720,7 @@ class ClaudemanApp {
} else {
this.terminal.clear();
this.showWelcome();
this.renderInnerStatePanel(); // Clear inner panel when no sessions
}
}
@@ -1970,8 +1973,24 @@ class ClaudemanApp {
}
toggleInnerStatePanel() {
// Preserve xterm scroll position to prevent jump when panel height changes
const xtermViewport = this.terminal?.element?.querySelector('.xterm-viewport');
const scrollTop = xtermViewport?.scrollTop;
this.innerStatePanelCollapsed = !this.innerStatePanelCollapsed;
this.renderInnerStatePanel();
// Restore scroll position and refit terminal after layout change
requestAnimationFrame(() => {
// Restore xterm scroll position
if (xtermViewport && scrollTop !== undefined) {
xtermViewport.scrollTop = scrollTop;
}
// Refit terminal to new container size
if (this.terminal && this.fitAddon) {
this.fitAddon.fit();
}
});
}
toggleRalphDetach() {
@@ -2099,14 +2118,6 @@ class ClaudemanApp {
// Update stats
this.updateRalphStats(state?.loop, completed, total);
// Update phrase preview
const phrasePreview = this.$('ralphPhrasePreview');
if (phrasePreview && state?.loop?.completionPhrase) {
phrasePreview.innerHTML = `<code>${this.escapeHtml(state.loop.completionPhrase)}</code>`;
} else if (phrasePreview) {
phrasePreview.textContent = '';
}
// Handle collapsed/expanded state
if (this.innerStatePanelCollapsed) {
panel.classList.add('collapsed');