From bff1c5368835fc28034086d86c05ddb686fbdc36 Mon Sep 17 00:00:00 2001 From: Steve Shreeve Date: Wed, 9 Sep 2026 11:23:07 -0600 Subject: [PATCH] Give each queued follow-up its own row The queued-message card drew every follow-up in a fixed 30px row with its text vertically centred and only `truncate` to keep it on one line. `truncate` stops soft wrapping, but a hard newline still breaks the text into several lines, and centring those in 30px paints the extra lines over the rows above and below and past the card's top edge. Any multi-line follow-up, a pasted terminal transcript or a file tree, overlapped its neighbours. A row is now its own box: it grows to its text, clips anything past that, top-aligns the queue icon and the controls with the first line, and a rule separates it from the row before. The text keeps its hard line breaks and wraps long lines, up to three lines in all with an ellipsis on the last, so a prompt is recognisable without the queue turning into a second transcript. A one-line row still measures 30px, so the common case looks as it did. --- src/app/composer.rs | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/app/composer.rs b/src/app/composer.rs index 276b533f..69ac07ea 100644 --- a/src/app/composer.rs +++ b/src/app/composer.rs @@ -2415,7 +2415,7 @@ impl Waku { let theme = Theme::current(cx); let steerable = self.session_can_steer(session); let mut list = div().flex().flex_col().py(px(4.0)); - for message in &session.queued_messages { + for (index, message) in session.queued_messages.iter().enumerate() { let message_id = message.id; let content = if message.visible_content().trim().is_empty() { message @@ -2508,29 +2508,41 @@ impl Waku { list = list.child( div() .id(SharedString::from(format!("queued-message-{message_id}"))) - .h(px(30.0)) + .min_h(px(30.0)) + .overflow_hidden() + .when(index > 0, |row| row.border_t_1().border_color(theme.border)) .pl(px(12.0)) .pr(px(6.0)) .flex() - .items_center() + .items_start() .gap(px(9.0)) .cursor_default() .tab_index(0) .focus_visible(|style| style.border_1().border_color(theme.accent)) .hover(|element| element.bg(theme.overlay)) .tooltip(Tooltip::text(tr!("composer.edit_in_composer"))) - .child(icon("icons/queue.svg", 12.0, theme.text_tertiary)) + .child(div().h(px(30.0)).flex().items_center().child(icon( + "icons/queue.svg", + 12.0, + theme.text_tertiary, + ))) .child( div() .flex_1() .min_w_0() - .truncate() + // Three lines is enough to recognise a prompt without + // the queue becoming a second transcript. + .py(px(6.0)) + .line_height(sp(18.0)) + .line_clamp(3) + .text_ellipsis() .text_size(sp(12.5)) .text_color(theme.text) .child(SharedString::from(content)), ) .child( div() + .h(px(30.0)) .flex() .items_center() .gap(px(2.0))