diff --git a/CLAUDE.md b/CLAUDE.md index 41407a44..afc67f1a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -35,7 +35,7 @@ When user says "COM": 1. Increment version in BOTH `package.json` AND `CLAUDE.md` (verify they match with `grep version package.json && grep Version CLAUDE.md`) 2. Run: `git add -A && git commit -m "chore: bump version to X.XXXX" && git push && npm run build && systemctl --user restart claudeman-web` -**Version**: 0.1525 (must match `package.json` for npm publish) +**Version**: 0.1526 (must match `package.json` for npm publish) ## Project Overview diff --git a/package.json b/package.json index a97b33fa..6758a2ef 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "claudeman", - "version": "0.1525", + "version": "0.1526", "description": "The missing control plane for Claude Code - run 20 autonomous agents with real-time monitoring and session persistence", "type": "module", "main": "dist/index.js", diff --git a/src/web/public/app.js b/src/web/public/app.js index 0e52a645..58c2d12b 100644 --- a/src/web/public/app.js +++ b/src/web/public/app.js @@ -14575,6 +14575,17 @@ class ClaudemanApp { modal.querySelectorAll('.modal-tabs .modal-tab-btn').forEach(btn => { btn.onclick = () => this.switchCaseModalTab(btn.dataset.tab); }); + // Scroll-into-view on focus for mobile keyboard visibility + modal.querySelectorAll('input[type="text"]').forEach(input => { + if (!input._mobileScrollWired) { + input._mobileScrollWired = true; + input.addEventListener('focus', () => { + if (window.innerWidth <= 430) { + setTimeout(() => input.scrollIntoView({ behavior: 'smooth', block: 'center' }), 300); + } + }); + } + }); modal.classList.add('active'); document.getElementById('newCaseName').focus(); } @@ -14606,10 +14617,19 @@ class ClaudemanApp { } async submitCaseModal() { - if (this.caseModalTab === 'case-create') { - await this.createCase(); - } else { - await this.linkCase(); + const btn = document.getElementById('caseModalSubmit'); + const originalText = btn.textContent; + btn.classList.add('loading'); + btn.textContent = this.caseModalTab === 'case-create' ? 'Creating...' : 'Linking...'; + try { + if (this.caseModalTab === 'case-create') { + await this.createCase(); + } else { + await this.linkCase(); + } + } finally { + btn.classList.remove('loading'); + btn.textContent = originalText; } } @@ -14771,8 +14791,12 @@ class ClaudemanApp { showCreateCaseFromMobile() { // Close mobile picker first this.closeMobileCasePicker(); - // Open the create case modal + // Open the create case modal with slide-up animation this.showCreateCaseModal(); + const modal = document.getElementById('createCaseModal'); + modal.classList.add('from-mobile'); + // Remove animation class after it plays + setTimeout(() => modal.classList.remove('from-mobile'), 300); } renderScreenSessions() { diff --git a/src/web/public/index.html b/src/web/public/index.html index 7750c560..51551f6c 100644 --- a/src/web/public/index.html +++ b/src/web/public/index.html @@ -1110,25 +1110,25 @@ diff --git a/src/web/public/mobile.css b/src/web/public/mobile.css index a9200575..6a931d96 100644 --- a/src/web/public/mobile.css +++ b/src/web/public/mobile.css @@ -1075,6 +1075,11 @@ html.mobile-init .file-browser-panel { overflow-y: auto; } + /* When keyboard opens in case modal, let body grow taller */ + .keyboard-visible #createCaseModal .modal-body { + max-height: 60vh; + } + /* Mobile Case Picker - Mobile-specific overrides */ .mobile-case-picker .modal-backdrop { background: rgba(0, 0, 0, 0.5); @@ -1128,6 +1133,98 @@ html.mobile-init .file-browser-panel { flex-shrink: 0; } + /* ---- Case Modal: Mobile Touch Optimizations ---- */ + + /* Larger tab buttons for case modal - easy to tap */ + #createCaseModal .modal-tabs { + gap: 0.5rem; + padding: 0.5rem 1rem 0.75rem; + } + + #createCaseModal .modal-tab-btn { + flex: 1; + min-height: 44px; + padding: 0.6rem 1rem; + font-size: 0.8rem; + font-weight: 500; + border-radius: 8px; + justify-content: center; + text-align: center; + } + + /* Touch-friendly form inputs in case modal */ + #createCaseModal .form-row { + margin-bottom: 1rem; + } + + #createCaseModal .form-row label { + font-size: 0.8rem; + margin-bottom: 0.4rem; + font-weight: 500; + color: #e5e7eb; + } + + #createCaseModal .form-row input[type="text"] { + min-height: 44px; + font-size: 16px; /* Prevents iOS zoom on focus */ + padding: 0.5rem 0.75rem; + border-radius: 8px; + } + + #createCaseModal .form-row .form-hint { + font-size: 0.65rem; + margin-top: 0.35rem; + line-height: 1.4; + } + + /* Touch-friendly action buttons in case modal */ + #createCaseModal .form-actions { + padding: 0.75rem 1rem; + padding-bottom: calc(0.75rem + var(--safe-area-bottom)); + gap: 0.75rem; + } + + #createCaseModal .form-actions .btn-toolbar { + min-height: 44px !important; + max-height: 44px !important; + height: 44px !important; + font-size: 0.85rem !important; + font-weight: 500; + border-radius: 8px; + } + + /* Loading state for submit button */ + #caseModalSubmit.loading { + opacity: 0.6; + pointer-events: none; + } + + /* Smooth open animation for case modal from mobile picker */ + #createCaseModal.from-mobile .modal-content { + animation: caseModalSlideUp 0.25s ease-out; + } + + @keyframes caseModalSlideUp { + from { + transform: translateY(30px); + opacity: 0; + } + to { + transform: translateY(0); + opacity: 1; + } + } + + /* Mobile case picker - larger create button (override btn-toolbar !important) */ + .btn-case-create-mobile { + min-height: 48px !important; + max-height: 48px !important; + height: 48px !important; + font-size: 0.85rem !important; + font-weight: 500; + border-radius: 10px; + } + /* Settings grid - single column on phones */ .settings-grid { grid-template-columns: 1fr;