diff --git a/lyra/web/static/index.html b/lyra/web/static/index.html index 6fdab29..06f58d1 100644 --- a/lyra/web/static/index.html +++ b/lyra/web/static/index.html @@ -116,8 +116,8 @@
- - + +
@@ -287,6 +287,8 @@ if (!msg) return; inputEl.value = ""; + autoGrow(inputEl); // collapse the box back to one line after clearing + addMessage("user", msg); history.push({ role: "user", content: msg }); await saveSession(); // ✅ persist both user + assistant messages @@ -548,6 +550,13 @@ return b; } + // Grow the input textarea to fit its content (up to a cap, then it scrolls). + function autoGrow(el) { + if (!el) return; + el.style.height = "auto"; + el.style.height = Math.min(el.scrollHeight, 140) + "px"; + } + function addMessage(role, text, autoScroll = true) { const messagesEl = document.getElementById("messages"); @@ -1004,11 +1013,15 @@ checkHealth(); setInterval(checkHealth, 10000); - // Input events + // Input events. Enter inserts a newline and grows the box (like the Claude + // app) — you tap the arrow to send. ⌘/Ctrl+Enter sends from the keyboard. document.getElementById("sendBtn").addEventListener("click", sendMessage); - document.getElementById("userInput").addEventListener("keypress", e => { - if (e.key === "Enter") sendMessage(); + const inputBox = document.getElementById("userInput"); + inputBox.addEventListener("input", () => autoGrow(inputBox)); + inputBox.addEventListener("keydown", e => { + if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) { e.preventDefault(); sendMessage(); } }); + autoGrow(inputBox); // ========== THINKING STREAM INTEGRATION ========== const thinkingPanel = document.getElementById("thinkingPanel"); diff --git a/lyra/web/static/style.css b/lyra/web/static/style.css index 7e014d3..c3f3f6a 100644 --- a/lyra/web/static/style.css +++ b/lyra/web/static/style.css @@ -199,6 +199,7 @@ button:hover, select:hover { /* Input bar */ #input { display: flex; + align-items: flex-end; /* arrow stays at the bottom as the textarea grows */ border-top: 1px solid var(--border); background: var(--bg-elev); padding: 10px; @@ -208,9 +209,14 @@ button:hover, select:hover { background: var(--bg-line); color: var(--text-main); border: 1px solid var(--border); - border-radius: 8px; + border-radius: 16px; padding: 9px 12px; font-family: var(--font-console); + font-size: 0.95rem; + line-height: 1.4; + resize: none; /* grown programmatically, not by the drag handle */ + max-height: 140px; + overflow-y: auto; transition: border-color .15s, box-shadow .15s; } #userInput::placeholder { color: var(--text-fade); } @@ -221,6 +227,16 @@ button:hover, select:hover { } #sendBtn { margin-left: 8px; + flex: none; + width: 38px; + height: 38px; + padding: 0; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-size: 1.25rem; + line-height: 1; background: var(--accent); color: #0a0a0a; border-color: var(--accent); @@ -936,12 +952,14 @@ select:hover { #userInput { font-size: 16px; /* Prevents zoom on iOS */ - padding: 12px; + padding: 11px 14px; } #sendBtn { - padding: 12px 16px; - font-size: 1rem; + width: 44px; /* comfortable touch target */ + height: 44px; + padding: 0; + font-size: 1.35rem; } /* Modal - full width on mobile */ @@ -1040,12 +1058,14 @@ select:hover { #userInput { font-size: 16px; - padding: 10px; + padding: 10px 13px; } #sendBtn { - padding: 10px 14px; - font-size: 0.95rem; + width: 42px; + height: 42px; + padding: 0; + font-size: 1.3rem; } .modal-header h3 {