fix: update mobile CSS for OpenCode run button group

Replace dead .btn-claude selectors in mobile.css with proper styling
for the new split run button (.btn-run + .btn-run-gear). Add mobile
touch-friendly dropdown menu options (10px padding, 35px height).
Include mode-specific colors for both Claude (blue) and OpenCode
(green) on mobile. Also guard Claude-specific features (Ralph,
Respawn) from running on OpenCode sessions in server.ts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
arkon
2026-02-26 15:06:36 +01:00
co-authored by Claude Opus 4.6
parent 2e3a08fad2
commit 33f39c91ba
5 changed files with 150 additions and 59 deletions
+37 -9
View File
@@ -4056,6 +4056,11 @@ class ClaudemanApp {
this.terminal.scrollToBottom();
// Re-position local echo overlay at new prompt location
this._localEchoOverlay?.rerender();
// Resize PTY to match actual browser dimensions (critical for OpenCode
// TUI sessions that render at fixed 120x40 until told the real size)
if (this.activeSessionId) {
this.sendResize(this.activeSessionId);
}
}
} catch (err) {
console.error('needsRefresh reload failed:', err);
@@ -6191,6 +6196,14 @@ class ClaudemanApp {
const sessionNameEl = document.getElementById('closeConfirmSessionName');
sessionNameEl.textContent = name;
// Update kill button text based on session mode
const killTitle = document.getElementById('closeConfirmKillTitle');
if (killTitle) {
killTitle.textContent = session.mode === 'opencode'
? 'Kill Tmux & OpenCode'
: 'Kill Tmux & Claude Code';
}
document.getElementById('closeConfirmModal').classList.add('active');
}
@@ -9629,9 +9642,9 @@ class ClaudemanApp {
const data = await res.json();
if (!data.success) throw new Error(data.error || 'Failed to start OpenCode');
// Switch to the new session
// Switch to the new session (don't pre-set activeSessionId — selectSession
// early-returns when IDs match, skipping buffer load and sendResize)
if (data.sessionId) {
this.activeSessionId = data.sessionId;
await this.selectSession(data.sessionId);
}
@@ -10461,13 +10474,28 @@ class ClaudemanApp {
document.getElementById('respawnPresetSelect').value = '';
document.getElementById('presetDescriptionHint').textContent = '';
// Populate Ralph Wiggum form with current session values
const ralphState = this.ralphStates.get(sessionId);
this.populateRalphForm({
enabled: ralphState?.loop?.enabled ?? session.ralphLoop?.enabled ?? false,
completionPhrase: ralphState?.loop?.completionPhrase || session.ralphLoop?.completionPhrase || '',
maxIterations: ralphState?.loop?.maxIterations || session.ralphLoop?.maxIterations || 0,
});
// Hide Ralph/Todo tab and Respawn tab for opencode sessions (not supported)
const ralphTabBtn = document.querySelector('#sessionOptionsModal .modal-tab-btn[data-tab="ralph"]');
const respawnTabBtn = document.querySelector('#sessionOptionsModal .modal-tab-btn[data-tab="respawn"]');
if (isOpenCode) {
if (ralphTabBtn) ralphTabBtn.style.display = 'none';
if (respawnTabBtn) respawnTabBtn.style.display = 'none';
// Default to Context tab for opencode sessions since Respawn is hidden
this.switchOptionsTab('context');
} else {
if (ralphTabBtn) ralphTabBtn.style.display = '';
if (respawnTabBtn) respawnTabBtn.style.display = '';
}
// Populate Ralph Wiggum form with current session values (skip for opencode)
if (!isOpenCode) {
const ralphState = this.ralphStates.get(sessionId);
this.populateRalphForm({
enabled: ralphState?.loop?.enabled ?? session.ralphLoop?.enabled ?? false,
completionPhrase: ralphState?.loop?.completionPhrase || session.ralphLoop?.completionPhrase || '',
maxIterations: ralphState?.loop?.maxIterations || session.ralphLoop?.maxIterations || 0,
});
}
const modal = document.getElementById('sessionOptionsModal');
modal.classList.add('active');
+2 -2
View File
@@ -782,10 +782,10 @@
<div class="close-options">
<button class="close-option" onclick="app.confirmCloseSession(false)">
<span class="close-option-title">Remove Tab</span>
<span class="close-option-desc">Screen session keeps running in background</span>
<span class="close-option-desc">Tmux session keeps running in background</span>
</button>
<button class="close-option close-option-danger" onclick="app.confirmCloseSession(true)">
<span class="close-option-title">Kill Tmux & Claude Code</span>
<span class="close-option-title" id="closeConfirmKillTitle">Kill Tmux & Claude Code</span>
<span class="close-option-desc">Terminate the session completely</span>
</button>
</div>
+69 -24
View File
@@ -560,26 +560,78 @@ html.mobile-init .file-browser-panel {
color: #fff;
}
/* Primary action button - Run Claude (matches arrow button blue) */
.btn-toolbar.btn-claude {
/* Run button group — split button with dropdown */
.run-btn-group {
display: flex;
flex: 0 0 auto;
padding: 0 0.75rem !important;
background: #1e3a5f;
border: 1px solid rgba(59, 130, 246, 0.3);
color: #93c5fd;
font-weight: 500;
}
.btn-toolbar.btn-claude:hover,
.btn-toolbar.btn-claude:active {
.btn-toolbar.btn-run {
flex: 0 0 auto;
padding: 0 0.6rem !important;
font-weight: 500;
border-radius: 4px 0 0 4px !important;
border-right: none !important;
}
.btn-toolbar.btn-run svg {
width: 10px;
height: 10px;
margin-right: 3px;
}
.btn-toolbar.btn-run-gear {
flex: 0 0 auto;
padding: 0 0.35rem !important;
min-width: unset !important;
border-radius: 0 4px 4px 0 !important;
border-left: 1px solid rgba(255,255,255,0.15) !important;
}
.btn-toolbar.btn-run-gear svg {
width: 10px;
height: 10px;
}
/* Claude mode colors on mobile */
.btn-toolbar.btn-run.mode-claude,
.btn-toolbar.btn-run-gear.mode-claude {
background: #1e3a5f;
border-color: rgba(59, 130, 246, 0.3);
color: #93c5fd;
}
.btn-toolbar.btn-run.mode-claude:active,
.btn-toolbar.btn-run-gear.mode-claude:active {
background: #2563eb;
border-color: rgba(59, 130, 246, 0.5);
}
.btn-toolbar.btn-claude svg {
width: 10px;
height: 10px;
margin-right: 4px;
/* OpenCode mode colors on mobile */
.btn-toolbar.btn-run.mode-opencode,
.btn-toolbar.btn-run-gear.mode-opencode {
background: #0a2e2a;
border-color: rgba(16, 185, 129, 0.3);
color: #6ee7b7;
}
.btn-toolbar.btn-run.mode-opencode:active,
.btn-toolbar.btn-run-gear.mode-opencode:active {
background: #0d4a40;
border-color: rgba(16, 185, 129, 0.5);
}
/* Run mode dropdown menu — positioned above toolbar on mobile */
.run-mode-menu {
bottom: 100%;
left: 0;
margin-bottom: 6px;
min-width: 140px;
}
.run-mode-option {
padding: 10px 12px;
font-size: 0.8rem;
}
/* Stop button - visible on mobile, icon-only */
@@ -617,19 +669,12 @@ html.mobile-init .file-browser-panel {
display: none !important;
}
/* Simplified toolbar layout - Run Claude, Shell, and Case */
/* Simplified toolbar layout — Run, Shell, and Case */
.toolbar-left .toolbar-group:first-child {
width: 100%;
gap: 8px;
}
.btn-toolbar.btn-claude {
flex: 0 0 auto;
min-width: fit-content;
white-space: nowrap;
padding: 0 10px !important;
}
.btn-toolbar.btn-shell {
flex: 0 0 auto;
min-width: fit-content;
@@ -643,7 +688,7 @@ html.mobile-init .file-browser-panel {
flex: 1 1 0 !important;
min-width: 0;
padding: 0 8px !important;
order: 2; /* Between Run Claude and Run Shell */
order: 2; /* Between Run and Run Shell */
overflow: hidden;
justify-content: center;
gap: 4px;
@@ -656,7 +701,7 @@ html.mobile-init .file-browser-panel {
white-space: nowrap;
}
/* Mobile case settings gear button - next to Run Claude */
/* Mobile case settings gear button - next to Run */
.btn-case-settings-mobile {
display: inline-flex !important;
align-items: center;
@@ -669,7 +714,7 @@ html.mobile-init .file-browser-panel {
color: #9ca3af;
cursor: pointer;
flex-shrink: 0;
order: 1; /* Next to Run Claude */
order: 1; /* Next to Run */
}
.btn-case-settings-mobile:active {