Skip to content

Commit b2ebe0d

Browse files
Fix agent tips not appearing below the warping indicator (warpdotdev#13122)
## Description The rotating agent tips that normally render below the "Warping..." text in Agent Mode stopped appearing. **Root cause:** PR warpdotdev#9297 (commit `76cccd24d`, "Clip warping-indicator chips so they don't overflow narrow panes") wrapped the warping indicator's row in a `Clipped` element so the action chips don't overflow into the adjacent pane on narrow widths. That row sits inside a `ConstrainedBox` whose height was already fixed to a single line of text. Before the clip was added, the tip rendered on a second line and simply overflowed the fixed-height box visibly. Once the row was clipped to the box's bounds, that second line — the agent tip (and the fallback-model explanation, which uses the same `secondary_element` slot) — was clipped away entirely. **Fix:** In `render_warping_indicator_base` (`app/src/ai/blocklist/block/view_impl/common.rs`), reserve room for the secondary line in the footer height when a `secondary_element` is present, so the clip no longer hides it while still clipping the chips horizontally as intended. The height math is extracted into a small pure helper `warping_footer_height(monospace_font_size, has_secondary_element)`. ## Linked Issue Reported in Slack (factory-client bug-triage): see thread link below. No GitHub issue. ## Testing - Added a regression unit test `warping_footer_height_reserves_a_line_for_the_secondary_element` in `common_tests.rs` that asserts the footer reserves an extra line (secondary font size + 1px margin) when a secondary element is present. It fails against the old single-line height and passes with the fix. - `cargo nextest run -p warp warping_footer_height` — passes. - `cargo clippy -p warp --lib --no-deps` — clean. - **Manual UI verification (computer use) on a running debug build — done.** Launched the authenticated `warp` build, started an agent, and confirmed: - Normal width: a tip line renders directly below `Warping...` (e.g. `Tip: /new to start a new agent conversation with clean context. Learn more`) and is fully visible, not clipped. Tips rotate as expected. - Narrow pane: the tip still renders (horizontally ellipsized to fit) and the action chips stay within the pane — i.e. warpdotdev#9297's chip-clipping is preserved alongside the restored tip. - Screenshots (normal + narrow width) are attached in the linked Slack thread. ### Screenshots / Videos Verification screenshots (normal-width tip restored; narrow-pane tip + chips) are posted in the linked Slack thread below. ## Agent Mode - [x] Warp Agent Mode - This PR was created via Warp's AI Agent Mode <!-- CHANGELOG-BUG-FIX: Fix the rotating agent tips not appearing below the "Warping..." indicator in Agent Mode. --> CHANGELOG-BUG-FIX: Fix the rotating agent tips not appearing below the "Warping..." indicator in Agent Mode. _Slack thread: https://warpdev.slack.com/archives/C0BCE7AELJ2/p1782518640801369?thread_ts=1782518640.801369&cid=C0BCE7AELJ2_ <!-- factory-client: {"source":"factory-client","slack_channel":"C0BCE7AELJ2","slack_thread_ts":"1782518640.801369","slack_permalink":"https://warpdev.slack.com/archives/C0BCE7AELJ2/p1782518640801369?thread_ts=1782518640.801369&cid=C0BCE7AELJ2","oz_run_id":"019f0663-f881-7ce6-89b3-73c050689d53","repo":"warpdotdev/warp"} --> Co-authored-by: Oz <oz-agent@warp.dev>
1 parent 11742b3 commit b2ebe0d

2 files changed

Lines changed: 47 additions & 3 deletions

File tree

app/src/ai/blocklist/block/view_impl/common.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,23 @@ pub struct WarpingIndicatorProps {
526526
pub secondary_element: Option<Box<dyn Element>>,
527527
}
528528

529+
/// Computes the fixed height of the warping-indicator footer.
530+
///
531+
/// The warping text occupies a single line. When a secondary element (an agent
532+
/// tip or fallback-model explanation) is present, it renders on a second line
533+
/// below the warping text, so the footer must reserve room for that extra line;
534+
/// otherwise the `Clipped` wrapper — which keeps action chips from overflowing
535+
/// narrow panes — also clips the secondary line. The extra line accounts for the
536+
/// secondary element's font size (`monospace_font_size - 3`, see
537+
/// `render_agent_tip` / `render_fallback_explanation`) plus its 1px top margin.
538+
fn warping_footer_height(monospace_font_size: f32, has_secondary_element: bool) -> f32 {
539+
let mut height = STATUS_FOOTER_VERTICAL_PADDING * 2. + monospace_font_size;
540+
if has_secondary_element {
541+
height += (monospace_font_size - 3.) + 1.;
542+
}
543+
height
544+
}
545+
529546
/// Helper function to render text in the "warping..." footer.
530547
/// Additional text that does not use the shimmering text animation can be passed in via
531548
/// `non_shimmering_text` which is useful if you want some part of the text to constantly update
@@ -543,6 +560,10 @@ pub fn render_warping_indicator_base(
543560
is_passive_code_diff,
544561
secondary_element,
545562
} = props;
563+
// Whether a secondary element (an agent tip or fallback-model explanation)
564+
// will be rendered on a second line below the warping text. Captured before
565+
// `secondary_element` is consumed so the container can reserve room for it.
566+
let has_secondary_element = secondary_element.is_some();
546567
// Unicode code point for the Warp glyph that is embedded in the version of Roboto we bundle
547568
// into the app. This code point MUST be rendered using Roboto (the default ui font) or else the
548569
// glyph may not be rendered.
@@ -646,7 +667,10 @@ pub fn render_warping_indicator_base(
646667
} else {
647668
let mut container = Container::new(
648669
ConstrainedBox::new(content)
649-
.with_height(STATUS_FOOTER_VERTICAL_PADDING * 2. + appearance.monospace_font_size())
670+
.with_height(warping_footer_height(
671+
appearance.monospace_font_size(),
672+
has_secondary_element,
673+
))
650674
.finish(),
651675
)
652676
.with_padding_right(CONTENT_HORIZONTAL_PADDING);

app/src/ai/blocklist/block/view_impl/common_tests.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ use super::{
1717
collect_visual_markdown_lightbox_collection, compute_visual_section_width,
1818
image_tooltip_handles_for_group, inline_image_source_label,
1919
is_supported_blocklist_image_source, lightbox_trigger_for_section, query_prefix_highlight_len,
20-
render_scrollable_collapsible_content, text_sections_with_indices, CollapsibleElementState,
21-
CollapsibleExpansionState, VisualMarkdownLightboxCollection,
20+
render_scrollable_collapsible_content, text_sections_with_indices, warping_footer_height,
21+
CollapsibleElementState, CollapsibleExpansionState, VisualMarkdownLightboxCollection,
2222
};
2323
use crate::ai::agent::{
2424
AIAgentInput, AIAgentTextSection, AgentOutputImage, AgentOutputImageLayout,
@@ -161,6 +161,26 @@ fn render_scrollable_collapsible_content_returns_none_when_collapsed() {
161161
);
162162
}
163163

164+
#[test]
165+
fn warping_footer_height_reserves_a_line_for_the_secondary_element() {
166+
// Regression: the warping indicator's footer is a fixed-height, clipped
167+
// container. When an agent tip (or fallback-model explanation) is present it
168+
// renders on a second line, so the footer must be taller than the
169+
// single-line case — otherwise the clip (added to keep action chips from
170+
// overflowing narrow panes) hides the tip entirely.
171+
let font_size = 13.;
172+
let without_tip = warping_footer_height(font_size, false);
173+
let with_tip = warping_footer_height(font_size, true);
174+
175+
assert!(
176+
with_tip > without_tip,
177+
"footer with a secondary element ({with_tip}) should be taller than without ({without_tip})",
178+
);
179+
// The extra room must cover the secondary line: its font size
180+
// (monospace_font_size - 3) plus the 1px top margin on the tip container.
181+
assert_eq!(with_tip - without_tip, (font_size - 3.) + 1.);
182+
}
183+
164184
#[test]
165185
fn compute_visual_section_width_rejects_non_finite_dimensions() {
166186
assert_eq!(compute_visual_section_width(f32::INFINITY, 20., 40.), None);

0 commit comments

Comments
 (0)