From 52f2d3d67d79eb5127a9a02b377a6f75c5691bce Mon Sep 17 00:00:00 2001 From: 0xPratik Date: Wed, 4 Nov 2026 19:29:06 +0545 Subject: [PATCH 1/2] fix(web): show the attachment tile above the composer The composer scrolled its own overflow at 70vh, which clipped the attachment tray floating above the message box to a sliver. The textarea already caps its height and scrolls, so the composer's scroll no longer kept any control in reach. Drop it, and with it the overflow exceptions for the send-back picker, model list and reviewer notes. Fixes #153 --- apps/web/src/styles.css | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/apps/web/src/styles.css b/apps/web/src/styles.css index 13f66762..03c135c5 100644 --- a/apps/web/src/styles.css +++ b/apps/web/src/styles.css @@ -1049,13 +1049,11 @@ h3 { gap: var(--space-2); flex: none; position: relative; - /* However long the text gets, the box stops at a share of the window and - the text scrolls inside it (#160): a `flex: none` row that outgrew the - column pushed the send, stop, attach and mic controls below the pane's - edge, where nothing could reach them. */ - max-height: 70vh; + /* The composer must not clip: the attachment tray, the send-back picker, + the model list and the reviewer's notes float above it. Long text stays + in reach because the textarea caps its own height and scrolls, so the + send, stop, attach and mic controls never leave the pane. */ min-height: 0; - overflow-y: auto; } /* The box itself is a flex column: textarea body above, action row beneath. @@ -1090,18 +1088,6 @@ h3 { overflow-y: auto; } -/* The send-back picker a hold on send raises, the reviewer's notes and the - model profile list float above the composer, anchored to it rather than the - viewport. The composer scrolls its own overflow (#160), which would clip them - above it, so it stops while one is open (#210). */ -.composer:has(> .sbpick), -.composer:has([data-slot="prompt-input-model-select"][data-state="open"]), -.composer:has(.reviewer-stance[data-open]), -.composer:has(.reviewer-stance:hover), -.composer:has(.reviewer-stance:focus-within) { - overflow: visible; -} - .document { border: 1px solid var(--wb-border); background: var(--wb-card); From 01551c082874c490178229a7bafef76852eacad3 Mon Sep 17 00:00:00 2001 From: 0xPratik Date: Wed, 4 Nov 2026 19:49:46 +0545 Subject: [PATCH 2/2] fix(web): scroll the notes above the composer box, not the composer Without a cap, the errors, the earlier-document caution and the suggested replies above the box could make the composer taller than a short pane and push the send, stop, attach and mic controls past its edge. Put back the 70vh cap and let those rows give way instead: they share one region that scrolls, so the box below keeps its full height and nothing clips the attachment tray floating above it. --- apps/web/src/pages/workspace/index.tsx | 102 +++++++++--------- .../pages/workspace/persistent-workspace.css | 2 +- apps/web/src/styles.css | 23 +++- 3 files changed, 73 insertions(+), 54 deletions(-) diff --git a/apps/web/src/pages/workspace/index.tsx b/apps/web/src/pages/workspace/index.tsx index bad69f36..0bab9f5e 100644 --- a/apps/web/src/pages/workspace/index.tsx +++ b/apps/web/src/pages/workspace/index.tsx @@ -1323,56 +1323,60 @@ export function StageWorkspace({ className="composer" data-working={working || sending ? "" : undefined} > - {attachFault === null ? null : ( -

- {attachFault} -

- )} - {sendFailed && sendFault ? ( -

- {sendFault} -

- ) : null} - {caution === null ? null : ( -
-

{wording.earlierDocument.warning(participantLabel(caution))}

-
- - {wording.earlierDocument.sendAnyway} - - { - setCaution(null); - composerRef.current?.focus(); - }} - > - {wording.action.cancel} - +
+ {attachFault === null ? null : ( +

+ {attachFault} +

+ )} + {sendFailed && sendFault ? ( +

+ {sendFault} +

+ ) : null} + {caution === null ? null : ( +
+

+ {wording.earlierDocument.warning(participantLabel(caution))} +

+
+ + {wording.earlierDocument.sendAnyway} + + { + setCaution(null); + composerRef.current?.focus(); + }} + > + {wording.action.cancel} + +
-
- )} - {replies.length > 0 && !providerMissing ? ( -
- {replies.map((reply) => ( - void deliver(reply)} - > - {reply} - - ))} -
- ) : null} + )} + {replies.length > 0 && !providerMissing ? ( +
+ {replies.map((reply) => ( + void deliver(reply)} + > + {reply} + + ))} +
+ ) : null} +
.workspace-fault { +.composer-notes > .workspace-fault { padding: 0; } diff --git a/apps/web/src/styles.css b/apps/web/src/styles.css index 03c135c5..656d4051 100644 --- a/apps/web/src/styles.css +++ b/apps/web/src/styles.css @@ -1049,13 +1049,28 @@ h3 { gap: var(--space-2); flex: none; position: relative; - /* The composer must not clip: the attachment tray, the send-back picker, - the model list and the reviewer's notes float above it. Long text stays - in reach because the textarea caps its own height and scrolls, so the - send, stop, attach and mic controls never leave the pane. */ + /* Capped so the send, stop, attach and mic controls never leave the pane. + The composer itself must not scroll: the attachment tray and the model + list float above the box, and a scrolling composer clips them. The + textarea scrolls its own text, and the notes above the box give way. */ + max-height: 70vh; min-height: 0; } +/* Errors, the earlier-document caution and suggested replies share one + region that scrolls once the composer reaches its cap, so the box below + keeps its full height. */ +.composer > .composer-notes { + display: grid; + gap: var(--space-2); + min-height: 0; + overflow-y: auto; +} + +.composer > .composer-notes:empty { + display: none; +} + /* The box itself is a flex column: textarea body above, action row beneath. Capping the box and letting the body scroll keeps the action row pinned at every text length. The textarea's own cap is the library's 200px; a