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 {