Fix SFTP panel to overlay terminal as a slide-out panel

Changed from flex-sibling layout (broken by absolute-positioned terminal
container) to an overlay approach: the SFTP panel is now position:absolute
on the right edge with a drop shadow, sliding over the terminal. The
resize handle is embedded inside the panel at its left edge.
This commit is contained in:
2026-04-16 00:00:00 +01:00
parent d5d0a5c27a
commit 2eb9406f05
2 changed files with 23 additions and 36 deletions
+21 -27
View File
@@ -4,9 +4,13 @@
========================================================================== */ ========================================================================== */
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
Panel wrapper — sits inside the session-panel as a flex sibling Panel wrapper — overlays the terminal from the right side
----------------------------------------------------------------------- */ ----------------------------------------------------------------------- */
.sftp-panel { .sftp-panel {
position: absolute;
top: 0;
right: 0;
bottom: 0;
width: 300px; width: 300px;
min-width: 220px; min-width: 220px;
max-width: 50vw; max-width: 50vw;
@@ -15,20 +19,26 @@
background: var(--bg-surface); background: var(--bg-surface);
border-left: 1px solid var(--border-subtle); border-left: 1px solid var(--border-subtle);
overflow: hidden; overflow: hidden;
flex-shrink: 0; z-index: var(--z-dropdown, 50);
box-shadow: -4px 0 16px rgba(0, 0, 0, 0.25);
} }
/* When the session panel has an SFTP panel, switch to row layout */ /* Resize handle — positioned at the left edge of the SFTP panel */
.session-panel.has-sftp { .sftp-resize-handle {
flex-direction: row; position: absolute;
top: 0;
left: -3px;
bottom: 0;
width: 6px;
cursor: col-resize;
background: transparent;
z-index: var(--z-dropdown, 50);
transition: background var(--transition-fast);
} }
/* Terminal container must become a flex child when SFTP panel is open */ .sftp-resize-handle:hover,
.session-panel.has-sftp .terminal-container { .sftp-resize-handle.is-dragging {
position: relative; background: var(--accent);
inset: unset;
flex: 1;
min-width: 0;
} }
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
@@ -327,19 +337,3 @@
outline: none; outline: none;
box-shadow: 0 0 0 2px var(--accent-muted); box-shadow: 0 0 0 2px var(--accent-muted);
} }
/* -----------------------------------------------------------------------
Resize handle between terminal and SFTP panel
----------------------------------------------------------------------- */
.sftp-resize-handle {
width: 4px;
cursor: col-resize;
background: transparent;
flex-shrink: 0;
transition: background var(--transition-fast);
}
.sftp-resize-handle:hover,
.sftp-resize-handle.is-dragging {
background: var(--accent);
}
+2 -9
View File
@@ -101,6 +101,7 @@ class SFTPBrowser {
// Build the panel DOM // Build the panel DOM
var panel = createElement('div', 'sftp-panel'); var panel = createElement('div', 'sftp-panel');
var handle = createElement('div', 'sftp-resize-handle'); var handle = createElement('div', 'sftp-resize-handle');
panel.appendChild(handle);
state.el = panel; state.el = panel;
state.handle = handle; state.handle = handle;
@@ -119,9 +120,7 @@ class SFTPBrowser {
this.panels.set(sessionId, state); this.panels.set(sessionId, state);
// Switch session panel to row layout and append // Append the overlay panel into the session panel
sessionPanel.classList.add('has-sftp');
sessionPanel.appendChild(handle);
sessionPanel.appendChild(panel); sessionPanel.appendChild(panel);
this._setupResize(sessionId, state); this._setupResize(sessionId, state);
@@ -142,12 +141,6 @@ class SFTPBrowser {
if (!state) return; if (!state) return;
state.el.remove(); state.el.remove();
state.handle.remove();
var sessionPanel = document.getElementById('panel-' + sessionId);
if (sessionPanel) {
sessionPanel.classList.remove('has-sftp');
}
this.panels.delete(sessionId); this.panels.delete(sessionId);
this._refitTerminal(sessionId); this._refitTerminal(sessionId);