web: align composer + button with the field; keep latest message visible above the attachment preview
- pin the textarea's resting height to 40px (padding+line-height+border) so it matches the 40px attach button; autosize adds the 2px border so a single line stays 40px. - scroll the feed to the bottom when the attachment preview appears/clears, so it no longer hides the most recent message.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2 files changed,
+13
−5
web/static/chat.js+7 −1web/static/style.css+6 −4
diff --git a/web/static/chat.js b/web/static/chat.js| index 5da276e..96102d9 100644 |
| --- a/web/static/chat.js |
| +++ b/web/static/chat.js |
| @@ -771,7 +771,9 @@ async function start(session) { |
| }; |
| const autosize = () => { |
| input.style.height = "auto"; |
| - input.style.height = Math.min(input.scrollHeight, 140) + "px"; |
| + // +2 compensates for the border (border-box scrollHeight excludes it), so a |
| + // single line renders at 40px — matching the attach button. |
| + input.style.height = Math.min(input.scrollHeight + 2, 140) + "px"; |
| }; |
| function clearPreview() { |
| @@ -779,6 +781,7 @@ async function start(session) { |
| previewBox.classList.add("hidden"); |
| previewBox.innerHTML = ""; |
| syncSendBtn(); |
| + feed.scrollTop = feed.scrollHeight; |
| } |
| function showPreview(file, uploading, meta) { |
| @@ -812,6 +815,9 @@ async function start(session) { |
| chip.appendChild(rm); |
| } |
| previewBox.appendChild(chip); |
| + // The preview takes vertical space below the feed; keep the latest message |
| + // in view rather than letting the preview cover it. |
| + feed.scrollTop = feed.scrollHeight; |
| } |
| // Downscale large images in the browser before upload (there's no server-side |
diff --git a/web/static/style.css b/web/static/style.css| index 36d360d..2b52302 100644 |
| --- a/web/static/style.css |
| +++ b/web/static/style.css |
| @@ -387,17 +387,19 @@ input:focus, textarea:focus { outline: 2px solid var(--accent); border-color: tr |
| flex: 1; |
| resize: none; |
| max-height: 140px; |
| - line-height: 1.4; |
| + /* 8+8 padding + 22 line + 2 border = 40px at rest, matching .attach-btn */ |
| + padding: 8px 46px 8px 14px; /* right room for the inline send button */ |
| + line-height: 22px; |
| + min-height: 40px; |
| border-radius: 20px; |
| font-family: inherit; |
| overflow: hidden; |
| - padding-right: 46px; /* room for the inline send button */ |
| } |
| /* circular up-arrow send button, tucked into the bottom-right of the field */ |
| .send-btn { |
| position: absolute; |
| - right: 5px; |
| - bottom: 5px; |
| + right: 4px; |
| + bottom: 3px; |
| width: 34px; |
| height: 34px; |
| padding: 0; |