feat(ui): flag agents awaiting a response, curate themes, fix theme-blind colors - #224
Open
BunsDev wants to merge 4 commits into
Open
feat(ui): flag agents awaiting a response, curate themes, fix theme-blind colors#224BunsDev wants to merge 4 commits into
BunsDev wants to merge 4 commits into
Conversation
…lind colors Three passes over the app's UI surfaces. Agent needs-response indicators A tab gave no signal when an agent in one of its panes was blocked waiting on the user, so a background tab could sit unanswered indefinitely. Tabs now show a needs-response indicator when any pane is blocked, and pane headers carry a matching chip. The state has two independent sources that both have to be checked: a plugin-backed CLI agent session and the Oz conversation. The conversation path alone is not sufficient, because selected_conversation_status_for_display returns None for a blocked-but-empty conversation. Bundled themes reduced to six The catalog had grown to 24, including ten background-image themes, three gradients, and two referral rewards that are unreachable in an OSS build. Kept CastCodes Dark, Dark, Light, Dracula, Solarized Dark and Gruvbox Dark. Retired ThemeKind variants stay in the enum so existing settings still deserialize and the chooser's sort order is preserved; they are hidden from the schema and resolve to a replacement of the same lightness. Theme-blind color literals Several render sites hard-coded a color that only works against one background lightness. The settings working-directory input drew black text on surface_2(), invisible in every dark theme; three tab bar icons fell back to white, invisible in Light; the account avatar used black initials on the accent fill. These now use the semantic accessors. active_highlighted_text_color() reads the primary_foreground token, which was defined in castcodes_ui_tokens but never consumed. Two dead translucent-white statics in the command palette were removed rather than re-themed. Adds app/src/ui_components/design.rs with the radius, spacing, type and motion steps from the Phase 1 contract. Colors were already tokenized; sizing had no code representation, so every call site wrote a bare literal. Inherited Warp views are migrated as they are touched rather than in one sweep, which would churn hundreds of visually unverifiable call sites.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR makes a set of UI-focused improvements aligned with the Phase 1 design contract: it surfaces “agent awaiting your response” state in both tabs and pane chrome, curates the bundled theme set down to the intended six, and fixes several theme-dependent contrast issues by routing through semantic theme accessors and adding a shared sizing scale.
Changes:
- Add a shared “awaiting user response” predicate for terminal panes, then surface it via a new tab-bar indicator and a “Needs response” chip in pane headers.
- Reduce bundled themes from 24 → 6 while preserving backwards-compatible deserialization for retired
ThemeKindvalues via a same-lightness replacement mapping. - Fix several hard-coded colors that broke on light/dark themes and introduce
ui_components::designconstants for radius/spacing/type/motion.
Reviewed changes
Copilot reviewed 24 out of 24 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| DESIGN-CHANGES.md | Documents the theme curation, contrast fixes, and the new sizing scale. |
| crates/warp_core/src/ui/theme/theme_tests.rs | Adds coverage for active_highlighted_text_color token fallback/override behavior. |
| crates/warp_core/src/ui/theme/color.rs | Updates active_highlighted_text_color() to prefer UiTokens::primary_foreground when present. |
| app/src/workspace/view/vertical_tabs.rs | Reuses shared “status pill with label” renderer for consistent status chips. |
| app/src/workspace/view.rs | Resets theme deletion to ThemeKind::default(); fixes avatar text color + font size via design scale. |
| app/src/ui_components/mod.rs | Exposes design module and ties shared border radius to the design scale. |
| app/src/ui_components/design.rs | Introduces a code-level sizing/type/motion vocabulary for Phase 1 contract values. |
| app/src/themes/theme.rs | Retires non-curated themes (schema-hidden, still deserializable), adds bundled-set helpers and replacement mapping, and limits preload to six themes. |
| app/src/themes/theme_tests.rs | Updates rendering invariants for the reduced built-in set; adds tests for curated set and retired-kind compatibility. |
| app/src/themes/theme_chooser.rs | Removes referral-theme filtering from the chooser item generation. |
| app/src/themes/mod.rs | Updates onboarding theme picker to draw from the curated bundled set. |
| app/src/themes/default_themes.rs | Removes definitions for retired decorative/referral themes; adds module docs explaining the curated set. |
| app/src/terminal/view/pane_impl.rs | Adds “Needs response” chip to pane headers; implements TerminalView::is_awaiting_user_response(). |
| app/src/terminal/view_tests.rs | Adds unit test covering CLI-agent-session blocked status path for is_awaiting_user_response(). |
| app/src/tab.rs | Adds Indicator::NeedsResponse and tooltip; fixes tab icon fallback colors for Light theme; adopts design radius for tab rounding. |
| app/src/settings/initializer.rs | Removes the “DefaultAdeberryTheme” new-user override now that Adeberry is retired. |
| app/src/settings_view/show_blocks_view.rs | Fixes overflow icon color to use a semantic theme accessor; aligns radius to 4px. |
| app/src/settings_view/features/working_directory.rs | Fixes input text color to be theme-correct on dark surfaces. |
| app/src/search/command_search/view.rs | Removes dead translucent-white color constants. |
| app/src/pane_group/mod.rs | Adds pane-group helper to count panes awaiting user response. |
| app/src/env_vars/env_var_collection_block.rs | Aligns env-var collection radius to the 8px contract maximum via a named constant. |
| app/src/auth/login_slide.rs | Simplifies visual selection mapping now that retired themes are no longer offered. |
| app/src/ai/document/orchestration_config_block.rs | Uses percentage radius for pill toggle track to express intent and keep pixel-identical appearance. |
| app/src/ai/conversation_status_ui.rs | Adds shared “status pill with label” renderer and adopts design scale constants for padding/radius/font size. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+831
to
+837
| /// Returns the needs-response indicator when any visible pane in this tab | ||
| /// (focused or not, Oz conversation or CLI agent session) is blocked | ||
| /// awaiting the user's response, so the user can spot it from the tab bar. | ||
| fn needs_response_indicator(tab: &TabData, ctx: &AppContext) -> Option<Indicator> { | ||
| let pane_count = tab.pane_group.as_ref(ctx).panes_awaiting_user_response(ctx); | ||
| (pane_count > 0).then_some(Indicator::NeedsResponse { pane_count }) | ||
| } |
Keep OSC 9/777 notifications enabled in OSS builds so local agent blocked states can reach the needs-response indicators. Add a channel-level regression test for the feature gate. Signed-off-by: Val Alexander <68980965+BunsDev@users.noreply.github.com>
Comment on lines
+831
to
+837
| /// Returns the needs-response indicator when any visible pane in this tab | ||
| /// (focused or not, Oz conversation or CLI agent session) is blocked | ||
| /// awaiting the user's response, so the user can spot it from the tab bar. | ||
| fn needs_response_indicator(tab: &TabData, ctx: &AppContext) -> Option<Indicator> { | ||
| let pane_count = tab.pane_group.as_ref(ctx).panes_awaiting_user_response(ctx); | ||
| (pane_count > 0).then_some(Indicator::NeedsResponse { pane_count }) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Three passes over the app's UI surfaces, from a review of the interface against the Phase 1 design contract. They share files (
tab.rs,workspace/view.rs,ai/conversation_status_ui.rseach carry hunks from more than one pass), so they land together rather than as three PRs whose diffs would have to be split hunk-by-hunk.1. Show when an agent is waiting on you
Why: a tab gave no signal when an agent in one of its panes was blocked awaiting a response, so a background tab could sit unanswered indefinitely.
How:
TerminalView::is_awaiting_user_responseis the shared predicate;PaneGroup::panes_awaiting_user_responsecounts blocked panes; the tab bar gains anIndicator::NeedsResponse { pane_count }and the pane header a "Needs response" chip.The blocked state has two independent sources and both have to be checked. Checking only the Oz conversation is not enough, because
selected_conversation_status_for_displayreturnsNonefor a conversation that is blocked but empty — so the CLI-agent session path is checked first.No new re-render plumbing was needed:
WorkspaceandTerminalViewalready subscribe toBlocklistAIHistoryModelandCLIAgentSessionsModeland notify on status change.2. Bundled themes reduced 24 → 6
Why: the catalog included ten background-image themes, three gradients, and two referral-reward themes that are unreachable in an OSS build.
How: kept CastCodes Dark, Dark, Light, Dracula, Solarized Dark, Gruvbox Dark.
Back-compat is deliberate: retired
ThemeKindvariants stay in the enum so existing settings still deserialize and the chooser's discriminant-ordered sort is preserved. They are hidden with#[schemars(skip)]and resolve through a newretired_replacement()to a theme of the same lightness, so a user on a retired theme is not flipped from dark to light. Covered byretired_theme_kinds_still_deserializeandretired_themes_resolve_to_a_same_lightness_replacement.3. Colors that only worked on one background lightness
These are correctness bugs, not styling preferences — each hard-codes a color that disappears or fails contrast on the other themes:
ColorU::black()onsurface_2()— invisible on every dark thememain_text_color(surface_2())ColorU::white()fallback — invisible on Lightactive_ui_text_color()#7c3aedaccent — fails contrastactive_highlighted_text_color()#b3bab8; 5px radiusnonactive_ui_text_color(); 4pxactive_highlighted_text_color()now reads theprimary_foregroundtoken, which was defined incastcodes_ui_tokensbut never consumed; the accessor itself had zero callers before this, so the change carries no regression risk elsewhere. Themes without auiblock keep the previously derived value.Adds
app/src/ui_components/design.rs— the radius, spacing, type and motion steps from the contract. Colors were already tokenized; sizing had no code representation, so every call site wrote a bare literal and review had nothing to check against.Deliberately not changed, after verifying each:
icon_with_status.rsdraws a black glyph on a fixed brand-purple ambient badge — not a theme surface, so black is contrast-correct.traffic_lights.rsuses white onWINDOWS_BRIGHT_REDfor the Windows close-button hover — platform convention.login_slide.rscopy reads as hosted-service marketing, but the login gate is unreachable in OSS builds (root_view.rsrequiresChannelState::cloud_services_available();auth_state.rsreturns early without it). Retoning it would be churn on a dead path.Linked Issue
Closes #223
ready-to-specorready-to-implement.Testing
Automated:
cargo check -p warp-app --bin cast-codes --features gui— clean, zero warnings (the design module's unused steps are covered by a scoped, documented#![allow(dead_code)]).cargo test -p warp_core ui::theme— 33 pass, including two new tests for theprimary_foregroundwiring and its fallback.cargo test -p warp-app --features gui --lib themes::— 42 pass, including three new tests for the six-theme curation and retired-kind back-compat.cargo test -p warp-app --features gui --lib settings_view::— 163 pass.is_awaiting_user_response_tracks_cli_session_blocked_statuscovers the CLI-session blocked path (it setslistener: Some(..); the pre-existing test atview_tests.rsuseslistener: Noneand only exercises the conversation path)../script/check_ai_attributionand./script/check_rebrand— pass.Not done, so a reviewer should treat these as open:
./script/runFull workspace nextest and doc tests passed with the exact commands used by
./script/presubmit. No integration test was added — the change is covered by unit tests at the model/predicate level.Screenshots / Videos
None — see the note above. Happy to add them if someone can capture a run.
Agent Mode
CHANGELOG-IMPROVEMENT: Tabs and pane headers now show when an agent is waiting on your response.
CHANGELOG-IMPROVEMENT: Reduced the bundled theme catalog to six curated themes.
CHANGELOG-BUG-FIX: Fixed text and icons that were invisible or low contrast on some themes, including the settings working-directory input on dark themes and tab bar icons on light themes.