[APP-4261] Add tooltips to disabled git operation buttons (#9234)
## Description Adds contextual tooltips to disabled git operation buttons so users understand why they can't click them. Tooltips are intentionally limited to **disabled states only** — enabled buttons don't get tooltips since their labels are self-explanatory. **Changes:** - Code review header: "No changes to commit" on the disabled Commit button; "No git actions available" on the disabled chevron - Commit dialog: "Enter a commit message" on the disabled Confirm button (only shown once file changes have loaded — silent during the async load window) - Bug fix: the PR #N button in the header was staying greyed out after transitioning from a disabled Commit mode, because `ViewPr` mode never called `set_disabled(false)` Linear: https://linear.app/warpdotdev/issue/APP-4261/git-buttons-should-all-have-tooltips Warp conversation: https://staging.warp.dev/conversation/27f5811f-22ea-4c4b-8d8f-47ff48a5b12b Loom: https://www.loom.com/share/932cfb22039c4566bcc7a7343b624d81 ## Testing Manually verified: - Commit button with no changes shows "No changes to commit" on hover - Chevron with no changes shows "No git actions available" on hover - Commit dialog Confirm button shows "Enter a commit message" once files load but message is empty; no tooltip shown during async load - PR #N button is no longer greyed out after committing all changes No new automated tests added — these are tooltip strings on existing button state logic that is already exercised by existing tests. ## Server API dependencies N/A — client-only change. ## Agent Mode - [x] Warp Agent Mode - This PR was created via Warp's AI Agent Mode ## Changelog Entries for Stable CHANGELOG-IMPROVEMENT: Git operation buttons now show tooltips explaining why they're disabled (e.g. "No changes to commit", "Enter a commit message"). Co-Authored-By: Oz <oz-agent@warp.dev> --------- Co-authored-by: Oz <oz-agent@warp.dev>
This commit is contained in:
@@ -6798,11 +6798,12 @@ impl CodeReviewView {
|
|||||||
|
|
||||||
match mode {
|
match mode {
|
||||||
PrimaryGitActionMode::Commit => {
|
PrimaryGitActionMode::Commit => {
|
||||||
let has_changes = self.has_uncommitted_changes(ctx);
|
let disabled = !self.has_uncommitted_changes(ctx);
|
||||||
self.git_primary_action_button.update(ctx, |button, ctx| {
|
self.git_primary_action_button.update(ctx, |button, ctx| {
|
||||||
button.set_label("Commit", ctx);
|
button.set_label("Commit", ctx);
|
||||||
button.set_icon(Some(Icon::GitCommit), ctx);
|
button.set_icon(Some(Icon::GitCommit), ctx);
|
||||||
button.set_disabled(!has_changes, ctx);
|
button.set_disabled(disabled, ctx);
|
||||||
|
button.set_tooltip(disabled.then_some("No changes to commit"), ctx);
|
||||||
button.set_on_click(
|
button.set_on_click(
|
||||||
|ctx| ctx.dispatch_typed_action(CodeReviewAction::OpenCommitDialog),
|
|ctx| ctx.dispatch_typed_action(CodeReviewAction::OpenCommitDialog),
|
||||||
ctx,
|
ctx,
|
||||||
@@ -6810,7 +6811,8 @@ impl CodeReviewView {
|
|||||||
button.set_adjoined_side(AdjoinedSide::Right, ctx);
|
button.set_adjoined_side(AdjoinedSide::Right, ctx);
|
||||||
});
|
});
|
||||||
self.git_operations_chevron.update(ctx, |button, ctx| {
|
self.git_operations_chevron.update(ctx, |button, ctx| {
|
||||||
button.set_disabled(!has_changes, ctx);
|
button.set_disabled(disabled, ctx);
|
||||||
|
button.set_tooltip(disabled.then_some("No git actions available"), ctx);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
PrimaryGitActionMode::Push => {
|
PrimaryGitActionMode::Push => {
|
||||||
@@ -6849,6 +6851,7 @@ impl CodeReviewView {
|
|||||||
self.git_primary_action_button.update(ctx, |button, ctx| {
|
self.git_primary_action_button.update(ctx, |button, ctx| {
|
||||||
button.set_label(label, ctx);
|
button.set_label(label, ctx);
|
||||||
button.set_icon(Some(Icon::Github), ctx);
|
button.set_icon(Some(Icon::Github), ctx);
|
||||||
|
button.set_disabled(false, ctx);
|
||||||
button.set_on_click(
|
button.set_on_click(
|
||||||
move |ctx| {
|
move |ctx| {
|
||||||
ctx.dispatch_typed_action(CodeReviewAction::ViewPr(url.clone()))
|
ctx.dispatch_typed_action(CodeReviewAction::ViewPr(url.clone()))
|
||||||
|
|||||||
@@ -241,6 +241,16 @@ pub(super) fn is_ready_to_confirm(state: &CommitState, app: &AppContext) -> bool
|
|||||||
!state.file_changes.is_empty() && commit_message(state, app).is_some()
|
!state.file_changes.is_empty() && commit_message(state, app).is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a tooltip to show on the disabled Confirm button when the
|
||||||
|
/// user needs to take action, or `None` when no tooltip is needed.
|
||||||
|
pub(super) fn confirm_tooltip(state: &CommitState, app: &AppContext) -> Option<&'static str> {
|
||||||
|
if !state.file_changes.is_empty() && commit_message(state, app).is_none() {
|
||||||
|
Some("Enter a commit message")
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Kicks off an open-time AI commit-message generation. On success, writes
|
/// Kicks off an open-time AI commit-message generation. On success, writes
|
||||||
/// the result into the message editor (unless the user has already typed
|
/// the result into the message editor (unless the user has already typed
|
||||||
/// something). On failure, silently swaps the placeholder to the manual
|
/// something). On failure, silently swaps the placeholder to the manual
|
||||||
|
|||||||
@@ -644,13 +644,17 @@ impl GitDialog {
|
|||||||
if self.loading {
|
if self.loading {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let disabled = match &self.mode {
|
let (disabled, tooltip) = match &self.mode {
|
||||||
GitDialogMode::Commit(state) => !commit::is_ready_to_confirm(state, ctx),
|
GitDialogMode::Commit(state) => (
|
||||||
GitDialogMode::Push(_) => false,
|
!commit::is_ready_to_confirm(state, ctx),
|
||||||
GitDialogMode::CreatePr(state) => !pr::is_ready_to_confirm(state),
|
commit::confirm_tooltip(state, ctx),
|
||||||
|
),
|
||||||
|
GitDialogMode::Push(_) => (false, None),
|
||||||
|
GitDialogMode::CreatePr(state) => (!pr::is_ready_to_confirm(state), None),
|
||||||
};
|
};
|
||||||
self.confirm_button.update(ctx, |b, ctx| {
|
self.confirm_button.update(ctx, |b, ctx| {
|
||||||
b.set_disabled(disabled, ctx);
|
b.set_disabled(disabled, ctx);
|
||||||
|
b.set_tooltip(tooltip, ctx);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user