diff --git a/frontend/src/css/sidebar.css b/frontend/src/css/sidebar.css index 37ebc60..2fe10b2 100644 --- a/frontend/src/css/sidebar.css +++ b/frontend/src/css/sidebar.css @@ -212,6 +212,33 @@ margin-top: 1px; } +/* Edit button (appears on hover, beside name) */ +.sidebar-item-edit { + flex-shrink: 0; + width: 22px; + height: 22px; + display: flex; + align-items: center; + justify-content: center; + font-size: 12px; + color: var(--text-disabled); + background: none; + border: none; + border-radius: var(--radius-sm); + cursor: pointer; + opacity: 0; + transition: opacity var(--transition-fast), color var(--transition-fast), background var(--transition-fast); +} + +.sidebar-item:hover .sidebar-item-edit { + opacity: 1; +} + +.sidebar-item-edit:hover { + color: var(--accent); + background: var(--bg-hover); +} + /* Favourite star */ .sidebar-item-star { flex-shrink: 0; diff --git a/frontend/src/js/app.js b/frontend/src/js/app.js index f8496c3..fe3409e 100644 --- a/frontend/src/js/app.js +++ b/frontend/src/js/app.js @@ -134,6 +134,10 @@ class App { window.runtime.EventsOn('session:state', (payload) => { this.tabs.updateSessionState(payload.sessionID, payload.state, payload.error); this.updateStatusBar(); + // Re-fit the terminal once connected so it picks up the final container size + if (payload.state === 'connected') { + setTimeout(() => this.terminals.fitActive(), 50); + } }); // Session closed by backend diff --git a/frontend/src/js/sidebar.js b/frontend/src/js/sidebar.js index d1866d9..eb0185a 100644 --- a/frontend/src/js/sidebar.js +++ b/frontend/src/js/sidebar.js @@ -170,6 +170,17 @@ class Sidebar { textWrapper.appendChild(subEl); item.appendChild(textWrapper); + // Edit button (visible on hover) + const editBtn = createElement('button', 'sidebar-item-edit', { + textContent: '✎', + title: 'Edit profile', + }); + editBtn.addEventListener('click', (e) => { + e.stopPropagation(); + this.app.profileEditor.openEdit(profile.id); + }); + item.appendChild(editBtn); + // Favourite star if (profile.favourite) { const star = createElement('span', 'sidebar-item-star is-favourite', { textContent: '★' }); diff --git a/frontend/src/js/terminal.js b/frontend/src/js/terminal.js index a02d175..34d1bc2 100644 --- a/frontend/src/js/terminal.js +++ b/frontend/src/js/terminal.js @@ -67,8 +67,14 @@ class TerminalManager { const container = document.getElementById(containerId); term.open(container); - // Initial fit - requestAnimationFrame(() => fitAddon.fit()); + // Fit the terminal once the container has had time to lay out. + // A single requestAnimationFrame is not enough — the panel may + // still be transitioning from display:none, so we retry briefly. + const doFit = () => { try { fitAddon.fit(); } catch (_) { /* noop */ } }; + requestAnimationFrame(doFit); + setTimeout(doFit, 50); + setTimeout(doFit, 150); + setTimeout(doFit, 400); // Forward user keystrokes to the backend term.onData((data) => {