From 580888263e25811d009d1e88a60eb9281bff6631 Mon Sep 17 00:00:00 2001 From: Roope Airinen Date: Wed, 1 Jul 2026 16:32:26 +0300 Subject: [PATCH 1/3] extract shared cancel button and add esc handling --- .../src/view/panels/popover.rs | 25 ++++++++++++++++++- .../popover/checkout_remote_branch_prompt.rs | 3 +-- .../src/view/panels/popover/clone_repo.rs | 8 +----- .../src/view/panels/popover/commit_prompt.rs | 8 +----- .../popover/conflict_save_stage_confirm.rs | 8 +----- .../popover/create_branch_from_ref_prompt.rs | 8 +----- .../view/panels/popover/create_tag_prompt.rs | 8 +----- .../popover/delete_remote_branch_confirm.rs | 8 +----- .../panels/popover/discard_changes_confirm.rs | 8 +----- .../popover/force_delete_branch_confirm.rs | 8 +----- .../view/panels/popover/force_push_confirm.rs | 8 +----- .../popover/force_remove_worktree_confirm.rs | 8 +----- .../panels/popover/merge_abort_confirm.rs | 8 +----- .../panels/popover/pull_reconcile_prompt.rs | 3 +-- .../popover/push_set_upstream_prompt.rs | 3 +-- .../view/panels/popover/remote_add_prompt.rs | 3 +-- .../panels/popover/remote_edit_url_prompt.rs | 3 +-- .../panels/popover/remote_remove_confirm.rs | 8 +----- .../src/view/panels/popover/reset_prompt.rs | 3 +-- .../view/panels/popover/stash_drop_confirm.rs | 8 +----- .../src/view/panels/popover/stash_prompt.rs | 4 +-- .../panels/popover/submodule_add_prompt.rs | 3 +-- .../submodule_change_pointer_prompt.rs | 3 +-- .../popover/submodule_remove_confirm.rs | 8 +----- .../popover/terminal_shutdown_confirm.rs | 3 +-- .../panels/popover/worktree_add_prompt.rs | 3 +-- .../panels/popover/worktree_remove_confirm.rs | 8 +----- 27 files changed, 50 insertions(+), 129 deletions(-) diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover.rs index 086991a6..2d6f10d6 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover.rs @@ -342,6 +342,9 @@ fn popover_is_confirm_dialog(kind: &PopoverKind) -> bool { | PopoverKind::ForceDeleteBranchConfirm { .. } | PopoverKind::ForceRemoveWorktreeConfirm { .. } | PopoverKind::DiscardChangesConfirm { .. } + | PopoverKind::ResetPrompt { .. } + | PopoverKind::PullReconcilePrompt { .. } + | PopoverKind::TerminalShutdownConfirm(_) | PopoverKind::Repo { kind: RepoPopoverKind::Remote(RemotePopoverKind::RemoveConfirm { .. }), .. @@ -374,6 +377,16 @@ pub(super) fn hotkey_hint( .child(label) } +pub(super) fn cancel_button( + id: &'static str, + hint_debug_selector: &'static str, + theme: AppTheme, +) -> components::Button { + components::Button::new(id, "Cancel") + .separated_end_slot(hotkey_hint(theme, hint_debug_selector, "Esc")) + .style(components::ButtonStyle::Outlined) +} + fn popover_anchor_corner(kind: &PopoverKind) -> Anchor { match kind { PopoverKind::PullPicker @@ -1302,6 +1315,11 @@ impl PopoverHost { kind: RepoPopoverKind::Submodule(SubmodulePopoverKind::AddPrompt), .. }) + | Some(PopoverKind::Repo { + kind: + RepoPopoverKind::Submodule(SubmodulePopoverKind::ChangePointerPrompt { .. }), + .. + }) ) || self.popover.as_ref().is_some_and(popover_is_confirm_dialog) } @@ -1373,7 +1391,12 @@ impl PopoverHost { Some(PopoverKind::CreateBranchFromRefPrompt { .. }) | Some(PopoverKind::StashPrompt) | Some(PopoverKind::CommitPrompt { .. }) - | Some(PopoverKind::StashPickerPrompt { .. }) => { + | Some(PopoverKind::StashPickerPrompt { .. }) + | Some(PopoverKind::Repo { + kind: + RepoPopoverKind::Submodule(SubmodulePopoverKind::ChangePointerPrompt { .. }), + .. + }) => { self.dismiss_inline_popover(window, cx) } Some(PopoverKind::CloneRepo) diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/checkout_remote_branch_prompt.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/checkout_remote_branch_prompt.rs index c0cf3f94..689b3746 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/checkout_remote_branch_prompt.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/checkout_remote_branch_prompt.rs @@ -60,9 +60,8 @@ pub(super) fn panel( .items_center() .justify_between() .child( - components::Button::new("checkout_remote_branch_cancel", "Cancel") + cancel_button("checkout_remote_branch_cancel", "checkout_remote_branch_cancel_hint", theme) .focus_handle(this.checkout_remote_branch_cancel_focus_handle.clone()) - .style(components::ButtonStyle::Outlined) .on_click(theme, cx, |this, _e, window, cx| { this.dismiss_prompt_popover(window, cx); }), diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/clone_repo.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/clone_repo.rs index 0825ba9c..74a97ee0 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/clone_repo.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/clone_repo.rs @@ -103,14 +103,8 @@ pub(super) fn panel(this: &mut PopoverHost, cx: &mut gpui::Context) .items_center() .justify_between() .child( - components::Button::new("clone_repo_cancel", "Cancel") + cancel_button("clone_repo_cancel", "clone_repo_cancel_hint", theme) .focus_handle(this.clone_repo_cancel_focus_handle.clone()) - .separated_end_slot(super::hotkey_hint( - theme, - "clone_repo_cancel_hint", - "Esc", - )) - .style(components::ButtonStyle::Outlined) .on_click(theme, cx, |this, _e, window, cx| { this.dismiss_prompt_popover(window, cx); }), diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/commit_prompt.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/commit_prompt.rs index 7e444477..42c84fe3 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/commit_prompt.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/commit_prompt.rs @@ -62,14 +62,8 @@ pub(super) fn panel( .items_center() .justify_between() .child( - components::Button::new("commit_prompt_cancel", "Cancel") + cancel_button("commit_prompt_cancel", "commit_prompt_cancel_hint", theme) .focus_handle(this.commit_prompt_cancel_focus_handle.clone()) - .separated_end_slot(super::hotkey_hint( - theme, - "commit_prompt_cancel_hint", - "Esc", - )) - .style(components::ButtonStyle::Outlined) .on_click(theme, cx, |this, _e, window, cx| { this.dismiss_prompt_popover(window, cx); }), diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/conflict_save_stage_confirm.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/conflict_save_stage_confirm.rs index 909d756c..b06f06f4 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/conflict_save_stage_confirm.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/conflict_save_stage_confirm.rs @@ -72,13 +72,7 @@ pub(super) fn panel( .items_center() .justify_between() .child( - components::Button::new("conflict_stage_cancel", "Cancel") - .separated_end_slot(super::hotkey_hint( - theme, - "conflict_stage_cancel_hint", - "Esc", - )) - .style(components::ButtonStyle::Outlined) + cancel_button("conflict_stage_cancel", "conflict_stage_cancel_hint", theme) .on_click(theme, cx, |this, _e, _w, cx| { this.popover = None; this.popover_anchor = None; diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/create_branch_from_ref_prompt.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/create_branch_from_ref_prompt.rs index 02b5c8c4..1ed64137 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/create_branch_from_ref_prompt.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/create_branch_from_ref_prompt.rs @@ -199,14 +199,8 @@ pub(super) fn panel( .items_center() .justify_between() .child( - components::Button::new("create_branch_from_ref_cancel", "Cancel") + cancel_button("create_branch_from_ref_cancel", "create_branch_from_ref_cancel_hint", theme) .focus_handle(this.create_branch_from_ref_cancel_focus_handle.clone()) - .separated_end_slot(hotkey_hint( - theme, - "create_branch_from_ref_cancel_hint", - "Esc", - )) - .style(components::ButtonStyle::Outlined) .on_click(theme, cx, |this, _e, window, cx| { this.dismiss_prompt_popover(window, cx); }), diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/create_tag_prompt.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/create_tag_prompt.rs index 1e07de11..6b76930d 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/create_tag_prompt.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/create_tag_prompt.rs @@ -166,14 +166,8 @@ pub(super) fn panel( .items_center() .justify_between() .child( - components::Button::new("create_tag_cancel", "Cancel") + cancel_button("create_tag_cancel", "create_tag_cancel_hint", theme) .focus_handle(this.create_tag_cancel_focus_handle.clone()) - .separated_end_slot(super::hotkey_hint( - theme, - "create_tag_cancel_hint", - "Esc", - )) - .style(components::ButtonStyle::Outlined) .on_click(theme, cx, |this, _e, window, cx| { this.dismiss_prompt_popover(window, cx); }), diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/delete_remote_branch_confirm.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/delete_remote_branch_confirm.rs index db151f52..2be6b476 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/delete_remote_branch_confirm.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/delete_remote_branch_confirm.rs @@ -59,13 +59,7 @@ pub(super) fn panel( .items_center() .justify_between() .child( - components::Button::new("delete_remote_branch_cancel", "Cancel") - .separated_end_slot(super::hotkey_hint( - theme, - "delete_remote_branch_cancel_hint", - "Esc", - )) - .style(components::ButtonStyle::Outlined) + cancel_button("delete_remote_branch_cancel", "delete_remote_branch_cancel_hint", theme) .on_click(theme, cx, |this, _e, _w, cx| { this.popover = None; this.popover_anchor = None; diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/discard_changes_confirm.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/discard_changes_confirm.rs index ab8ca611..94d8acf9 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/discard_changes_confirm.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/discard_changes_confirm.rs @@ -96,13 +96,7 @@ pub(super) fn panel( .items_center() .justify_between() .child( - components::Button::new("discard_changes_cancel", "Cancel") - .separated_end_slot(super::hotkey_hint( - theme, - "discard_changes_cancel_hint", - "Esc", - )) - .style(components::ButtonStyle::Outlined) + cancel_button("discard_changes_cancel", "discard_changes_cancel_hint", theme) .on_click(theme, cx, |this, _e, _w, cx| { this.popover = None; this.popover_anchor = None; diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/force_delete_branch_confirm.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/force_delete_branch_confirm.rs index a855b17c..24668524 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/force_delete_branch_confirm.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/force_delete_branch_confirm.rs @@ -55,13 +55,7 @@ pub(super) fn panel( .items_center() .justify_between() .child( - components::Button::new("force_delete_branch_cancel", "Cancel") - .separated_end_slot(super::hotkey_hint( - theme, - "force_delete_branch_cancel_hint", - "Esc", - )) - .style(components::ButtonStyle::Outlined) + cancel_button("force_delete_branch_cancel", "force_delete_branch_cancel_hint", theme) .on_click(theme, cx, |this, _e, _w, cx| { this.popover = None; this.popover_anchor = None; diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/force_push_confirm.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/force_push_confirm.rs index dfcce1ff..f70bf9fd 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/force_push_confirm.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/force_push_confirm.rs @@ -75,13 +75,7 @@ pub(super) fn panel( .items_center() .justify_between() .child( - components::Button::new("force_push_cancel", "Cancel") - .separated_end_slot(super::hotkey_hint( - theme, - "force_push_cancel_hint", - "Esc", - )) - .style(components::ButtonStyle::Outlined) + cancel_button("force_push_cancel", "force_push_cancel_hint", theme) .on_click(theme, cx, |this, _e, _w, cx| { this.popover = None; this.popover_anchor = None; diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/force_remove_worktree_confirm.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/force_remove_worktree_confirm.rs index 29a6020d..ae87d0e3 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/force_remove_worktree_confirm.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/force_remove_worktree_confirm.rs @@ -71,13 +71,7 @@ pub(super) fn panel( .items_center() .justify_between() .child( - components::Button::new("force_remove_worktree_cancel", "Cancel") - .separated_end_slot(super::hotkey_hint( - theme, - "force_remove_worktree_cancel_hint", - "Esc", - )) - .style(components::ButtonStyle::Outlined) + cancel_button("force_remove_worktree_cancel", "force_remove_worktree_cancel_hint", theme) .on_click(theme, cx, |this, _e, _w, cx| { this.popover = None; this.popover_anchor = None; diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/merge_abort_confirm.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/merge_abort_confirm.rs index d5fbd5a1..e1cd7bfa 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/merge_abort_confirm.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/merge_abort_confirm.rs @@ -86,13 +86,7 @@ pub(super) fn panel( .items_center() .justify_between() .child( - components::Button::new("merge_abort_cancel", "Cancel") - .separated_end_slot(super::hotkey_hint( - theme, - "merge_abort_cancel_hint", - "Esc", - )) - .style(components::ButtonStyle::Outlined) + cancel_button("merge_abort_cancel", "merge_abort_cancel_hint", theme) .on_click(theme, cx, |this, _e, _w, cx| { this.popover = None; this.popover_anchor = None; diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/pull_reconcile_prompt.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/pull_reconcile_prompt.rs index 1f8be854..56120859 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/pull_reconcile_prompt.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/pull_reconcile_prompt.rs @@ -57,8 +57,7 @@ pub(super) fn panel( .items_center() .justify_between() .child( - components::Button::new("pull_reconcile_cancel", "Cancel") - .style(components::ButtonStyle::Outlined) + cancel_button("pull_reconcile_cancel", "pull_reconcile_cancel_hint", theme) .on_click(theme, cx, |this, _e, _w, cx| { this.popover = None; this.popover_anchor = None; diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/push_set_upstream_prompt.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/push_set_upstream_prompt.rs index 022fb214..9d2868ab 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/push_set_upstream_prompt.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/push_set_upstream_prompt.rs @@ -48,9 +48,8 @@ pub(super) fn panel( .items_center() .justify_between() .child( - components::Button::new("push_upstream_cancel", "Cancel") + cancel_button("push_upstream_cancel", "push_upstream_cancel_hint", theme) .focus_handle(this.push_upstream_cancel_focus_handle.clone()) - .style(components::ButtonStyle::Outlined) .on_click(theme, cx, |this, _e, window, cx| { this.dismiss_prompt_popover(window, cx); }), diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/remote_add_prompt.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/remote_add_prompt.rs index 971fcef5..92531792 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/remote_add_prompt.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/remote_add_prompt.rs @@ -63,9 +63,8 @@ pub(super) fn panel( .items_center() .justify_between() .child( - components::Button::new("add_remote_cancel", "Cancel") + cancel_button("add_remote_cancel", "add_remote_cancel_hint", theme) .focus_handle(this.remote_add_cancel_focus_handle.clone()) - .style(components::ButtonStyle::Outlined) .on_click(theme, cx, |this, _e, window, cx| { this.dismiss_prompt_popover(window, cx); }), diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/remote_edit_url_prompt.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/remote_edit_url_prompt.rs index 347e3597..593920cf 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/remote_edit_url_prompt.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/remote_edit_url_prompt.rs @@ -53,9 +53,8 @@ pub(super) fn panel( .items_center() .justify_between() .child( - components::Button::new("edit_remote_url_cancel", "Cancel") + cancel_button("edit_remote_url_cancel", "edit_remote_url_cancel_hint", theme) .focus_handle(this.remote_edit_cancel_focus_handle.clone()) - .style(components::ButtonStyle::Outlined) .on_click(theme, cx, |this, _e, window, cx| { this.dismiss_prompt_popover(window, cx); }), diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/remote_remove_confirm.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/remote_remove_confirm.rs index f2f829bd..09cc7af0 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/remote_remove_confirm.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/remote_remove_confirm.rs @@ -40,13 +40,7 @@ pub(super) fn panel( .items_center() .justify_between() .child( - components::Button::new("remove_remote_cancel", "Cancel") - .separated_end_slot(super::hotkey_hint( - theme, - "remove_remote_cancel_hint", - "Esc", - )) - .style(components::ButtonStyle::Outlined) + cancel_button("remove_remote_cancel", "remove_remote_cancel_hint", theme) .on_click(theme, cx, |this, _e, _w, cx| { this.popover = None; this.popover_anchor = None; diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/reset_prompt.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/reset_prompt.rs index 7bcf8f3e..6679c741 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/reset_prompt.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/reset_prompt.rs @@ -58,8 +58,7 @@ pub(super) fn panel( .items_center() .justify_between() .child( - components::Button::new("reset_cancel", "Cancel") - .style(components::ButtonStyle::Outlined) + cancel_button("reset_cancel", "reset_cancel_hint", theme) .on_click(theme, cx, |this, _e, _w, cx| { this.popover = None; this.popover_anchor = None; diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/stash_drop_confirm.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/stash_drop_confirm.rs index a77fa005..c2e24273 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/stash_drop_confirm.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/stash_drop_confirm.rs @@ -64,13 +64,7 @@ pub(super) fn panel( .items_center() .justify_between() .child( - components::Button::new("stash_drop_confirm_cancel", "Cancel") - .separated_end_slot(super::hotkey_hint( - theme, - "stash_drop_cancel_hint", - "Esc", - )) - .style(components::ButtonStyle::Outlined) + cancel_button("stash_drop_confirm_cancel", "stash_drop_cancel_hint", theme) .on_click(theme, cx, move |this, _e, _w, cx| { this.store.dispatch(Msg::LoadStashes { repo_id }); this.popover = None; diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/stash_prompt.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/stash_prompt.rs index d7e83de5..0a53157b 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/stash_prompt.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/stash_prompt.rs @@ -35,10 +35,8 @@ pub(super) fn panel(this: &mut PopoverHost, cx: &mut gpui::Context) .items_center() .justify_between() .child( - components::Button::new("stash_cancel", "Cancel") + cancel_button("stash_cancel", "stash_cancel_hint", theme) .focus_handle(this.stash_cancel_focus_handle.clone()) - .separated_end_slot(super::hotkey_hint(theme, "stash_cancel_hint", "Esc")) - .style(components::ButtonStyle::Outlined) .on_click(theme, cx, |this, _e, window, cx| { this.dismiss_prompt_popover(window, cx); }), diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/submodule_add_prompt.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/submodule_add_prompt.rs index 571ca887..aad9a98d 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/submodule_add_prompt.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/submodule_add_prompt.rs @@ -189,9 +189,8 @@ pub(super) fn panel( .items_center() .justify_between() .child( - components::Button::new("submodule_add_cancel", "Cancel") + cancel_button("submodule_add_cancel", "submodule_add_cancel_hint", theme) .focus_handle(this.submodule_cancel_focus_handle.clone()) - .style(components::ButtonStyle::Outlined) .on_click(theme, cx, |this, _e, window, cx| { this.dismiss_prompt_popover(window, cx); }), diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/submodule_change_pointer_prompt.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/submodule_change_pointer_prompt.rs index e4cbf23a..d8577d9e 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/submodule_change_pointer_prompt.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/submodule_change_pointer_prompt.rs @@ -57,8 +57,7 @@ pub(super) fn panel( .items_center() .justify_between() .child( - components::Button::new("submodule_change_pointer_cancel", "Cancel") - .style(components::ButtonStyle::Outlined) + cancel_button("submodule_change_pointer_cancel", "submodule_change_pointer_cancel_hint", theme) .on_click(theme, cx, |this, _e, window, cx| { this.dismiss_inline_popover(window, cx); }), diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/submodule_remove_confirm.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/submodule_remove_confirm.rs index 1ac541b2..677a169f 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/submodule_remove_confirm.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/submodule_remove_confirm.rs @@ -40,13 +40,7 @@ pub(super) fn panel( .items_center() .justify_between() .child( - components::Button::new("submodule_remove_cancel", "Cancel") - .separated_end_slot(super::hotkey_hint( - theme, - "submodule_remove_cancel_hint", - "Esc", - )) - .style(components::ButtonStyle::Outlined) + cancel_button("submodule_remove_cancel", "submodule_remove_cancel_hint", theme) .on_click(theme, cx, |this, _e, _w, cx| { this.popover = None; this.popover_anchor = None; diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/terminal_shutdown_confirm.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/terminal_shutdown_confirm.rs index 4895af98..9477c7d7 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/terminal_shutdown_confirm.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/terminal_shutdown_confirm.rs @@ -95,8 +95,7 @@ pub(super) fn panel( .items_center() .justify_between() .child( - components::Button::new("terminal_shutdown_cancel", "Cancel") - .style(components::ButtonStyle::Outlined) + cancel_button("terminal_shutdown_cancel", "terminal_shutdown_cancel_hint", theme) .on_click(theme, cx, |this, _e, _window, cx| { let root_view = this.root_view.clone(); let _ = root_view.update(cx, |root, cx| { diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/worktree_add_prompt.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/worktree_add_prompt.rs index 1728de00..54b70947 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/worktree_add_prompt.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/worktree_add_prompt.rs @@ -160,9 +160,8 @@ pub(super) fn panel( .items_center() .justify_between() .child( - components::Button::new("worktree_add_cancel", "Cancel") + cancel_button("worktree_add_cancel", "worktree_add_cancel_hint", theme) .focus_handle(this.worktree_cancel_focus_handle.clone()) - .style(components::ButtonStyle::Outlined) .on_click(theme, cx, |this, _e, window, cx| { this.dismiss_prompt_popover(window, cx); }), diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/worktree_remove_confirm.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/worktree_remove_confirm.rs index 289bb3b8..05cdb46b 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/worktree_remove_confirm.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/worktree_remove_confirm.rs @@ -62,13 +62,7 @@ pub(super) fn panel( .items_center() .justify_between() .child( - components::Button::new("worktree_remove_cancel", "Cancel") - .separated_end_slot(super::hotkey_hint( - theme, - "worktree_remove_cancel_hint", - "Esc", - )) - .style(components::ButtonStyle::Outlined) + cancel_button("worktree_remove_cancel", "worktree_remove_cancel_hint", theme) .on_click(theme, cx, |this, _e, _w, cx| { this.popover = None; this.popover_anchor = None; From 267d5e912e252202998f1881350f588d6d8799e4 Mon Sep 17 00:00:00 2001 From: Roope Airinen Date: Wed, 1 Jul 2026 17:17:09 +0300 Subject: [PATCH 2/3] extract popover UI helpers and wire up Esc for all dialogs --- .../src/view/panels/popover.rs | 31 +- .../src/view/panels/popover/branch_picker.rs | 9 +- .../popover/checkout_remote_branch_prompt.rs | 32 +-- .../src/view/panels/popover/clone_repo.rs | 27 +- .../src/view/panels/popover/commit_prompt.rs | 9 +- .../popover/conflict_save_stage_confirm.rs | 9 +- .../popover/create_branch_from_ref_prompt.rs | 41 +-- .../view/panels/popover/create_tag_prompt.rs | 9 +- .../popover/delete_remote_branch_confirm.rs | 25 +- .../panels/popover/discard_changes_confirm.rs | 25 +- .../popover/force_delete_branch_confirm.rs | 9 +- .../view/panels/popover/force_push_confirm.rs | 18 +- .../popover/force_remove_worktree_confirm.rs | 25 +- .../panels/popover/merge_abort_confirm.rs | 18 +- .../panels/popover/pull_reconcile_prompt.rs | 9 +- .../popover/push_set_upstream_prompt.rs | 9 +- .../view/panels/popover/remote_add_prompt.rs | 27 +- .../panels/popover/remote_edit_url_prompt.rs | 23 +- .../panels/popover/remote_remove_confirm.rs | 9 +- .../src/view/panels/popover/reset_prompt.rs | 18 +- .../view/panels/popover/stash_drop_confirm.rs | 9 +- .../panels/popover/stash_picker_prompt.rs | 9 +- .../src/view/panels/popover/stash_prompt.rs | 9 +- .../panels/popover/submodule_add_prompt.rs | 45 +-- .../submodule_change_pointer_prompt.rs | 30 +- .../popover/submodule_remove_confirm.rs | 25 +- .../panels/popover/submodule_trust_confirm.rs | 9 +- .../popover/terminal_shutdown_confirm.rs | 29 +- .../src/view/panels/popover/tests/dialog.rs | 269 ++++++++++++++++++ .../src/view/panels/popover/tests/mod.rs | 1 + .../panels/popover/worktree_add_prompt.rs | 18 +- .../panels/popover/worktree_remove_confirm.rs | 25 +- 32 files changed, 450 insertions(+), 410 deletions(-) create mode 100644 crates/gitcomet-ui-gpui/src/view/panels/popover/tests/dialog.rs diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover.rs index 2d6f10d6..df762d07 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover.rs @@ -387,6 +387,25 @@ pub(super) fn cancel_button( .style(components::ButtonStyle::Outlined) } +pub(super) fn popover_title(title: impl Into) -> gpui::Div { + let title: SharedString = title.into(); + div() + .px_2() + .py_1() + .text_sm() + .font_weight(FontWeight::BOLD) + .child(title) +} + +pub(super) fn input_label(theme: AppTheme, label: &'static str) -> gpui::Div { + div() + .px_2() + .py_1() + .text_xs() + .text_color(theme.colors.text_muted) + .child(label) +} + fn popover_anchor_corner(kind: &PopoverKind) -> Anchor { match kind { PopoverKind::PullPicker @@ -1316,8 +1335,9 @@ impl PopoverHost { .. }) | Some(PopoverKind::Repo { - kind: - RepoPopoverKind::Submodule(SubmodulePopoverKind::ChangePointerPrompt { .. }), + kind: RepoPopoverKind::Submodule( + SubmodulePopoverKind::ChangePointerPrompt { .. } + ), .. }) ) || self.popover.as_ref().is_some_and(popover_is_confirm_dialog) @@ -1393,12 +1413,9 @@ impl PopoverHost { | Some(PopoverKind::CommitPrompt { .. }) | Some(PopoverKind::StashPickerPrompt { .. }) | Some(PopoverKind::Repo { - kind: - RepoPopoverKind::Submodule(SubmodulePopoverKind::ChangePointerPrompt { .. }), + kind: RepoPopoverKind::Submodule(SubmodulePopoverKind::ChangePointerPrompt { .. }), .. - }) => { - self.dismiss_inline_popover(window, cx) - } + }) => self.dismiss_inline_popover(window, cx), Some(PopoverKind::CloneRepo) | Some(PopoverKind::RecentRepositoryPicker) | Some(PopoverKind::CreateTagPrompt { .. }) diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/branch_picker.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/branch_picker.rs index 235ea279..e54efdf4 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/branch_picker.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/branch_picker.rs @@ -21,14 +21,7 @@ pub(super) fn panel(this: &mut PopoverHost, cx: &mut gpui::Context) .flex_col() .min_w(scaled_px(420.0)) .max_w(scaled_px(820.0)) - .child( - div() - .px_2() - .py_1() - .text_sm() - .font_weight(FontWeight::BOLD) - .child(title), - ) + .child(popover_title(title)) .child(div().border_t_1().border_color(theme.colors.border)); if let Some(repo) = this.active_repo() { diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/checkout_remote_branch_prompt.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/checkout_remote_branch_prompt.rs index 689b3746..fd599112 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/checkout_remote_branch_prompt.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/checkout_remote_branch_prompt.rs @@ -18,14 +18,7 @@ pub(super) fn panel( .flex() .flex_col() .w(scaled_px(540.0)) - .child( - div() - .px_2() - .py_1() - .text_sm() - .font_weight(FontWeight::BOLD) - .child("Checkout remote branch"), - ) + .child(popover_title("Checkout remote branch")) .child(div().border_t_1().border_color(theme.colors.border)) .child( div() @@ -35,14 +28,7 @@ pub(super) fn panel( .text_color(theme.colors.text_muted) .child(format!("Remote branch: {upstream}")), ) - .child( - div() - .px_2() - .py_1() - .text_xs() - .text_color(theme.colors.text_muted) - .child("Local branch name"), - ) + .child(input_label(theme, "Local branch name")) .child( div() .px_2() @@ -60,11 +46,15 @@ pub(super) fn panel( .items_center() .justify_between() .child( - cancel_button("checkout_remote_branch_cancel", "checkout_remote_branch_cancel_hint", theme) - .focus_handle(this.checkout_remote_branch_cancel_focus_handle.clone()) - .on_click(theme, cx, |this, _e, window, cx| { - this.dismiss_prompt_popover(window, cx); - }), + cancel_button( + "checkout_remote_branch_cancel", + "checkout_remote_branch_cancel_hint", + theme, + ) + .focus_handle(this.checkout_remote_branch_cancel_focus_handle.clone()) + .on_click(theme, cx, |this, _e, window, cx| { + this.dismiss_prompt_popover(window, cx); + }), ) .child( components::Button::new("checkout_remote_branch_go", "Checkout") diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/clone_repo.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/clone_repo.rs index 74a97ee0..f6457d6a 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/clone_repo.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/clone_repo.rs @@ -10,23 +10,9 @@ pub(super) fn panel(this: &mut PopoverHost, cx: &mut gpui::Context) .flex() .flex_col() .w(scaled_px(420.0)) - .child( - div() - .px_2() - .py_1() - .text_sm() - .font_weight(FontWeight::BOLD) - .child("Clone repository"), - ) + .child(popover_title("Clone repository")) .child(div().border_t_1().border_color(theme.colors.border)) - .child( - div() - .px_2() - .py_1() - .text_xs() - .text_color(theme.colors.text_muted) - .child("Repository URL / Path"), - ) + .child(input_label(theme, "Repository URL / Path")) .child( div() .px_2() @@ -35,14 +21,7 @@ pub(super) fn panel(this: &mut PopoverHost, cx: &mut gpui::Context) .min_w(px(0.0)) .child(this.clone_repo_url_input.clone()), ) - .child( - div() - .px_2() - .py_1() - .text_xs() - .text_color(theme.colors.text_muted) - .child("Destination parent folder"), - ) + .child(input_label(theme, "Destination parent folder")) .child( div() .px_2() diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/commit_prompt.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/commit_prompt.rs index 42c84fe3..df398838 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/commit_prompt.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/commit_prompt.rs @@ -14,14 +14,7 @@ pub(super) fn panel( .flex() .flex_col() .w(scaled_px(420.0)) - .child( - div() - .px_2() - .py_1() - .text_sm() - .font_weight(FontWeight::BOLD) - .child("Commit Changes"), - ) + .child(popover_title("Commit Changes")) .child(div().border_t_1().border_color(theme.colors.border)) .child( div() diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/conflict_save_stage_confirm.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/conflict_save_stage_confirm.rs index b06f06f4..be6b000b 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/conflict_save_stage_confirm.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/conflict_save_stage_confirm.rs @@ -46,14 +46,7 @@ pub(super) fn panel( .flex() .flex_col() .min_w(scaled_px(360.0)) - .child( - div() - .px_2() - .py_1() - .text_sm() - .font_weight(FontWeight::BOLD) - .child(title), - ) + .child(popover_title(title)) .child(div().border_t_1().border_color(theme.colors.border)) .child( div() diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/create_branch_from_ref_prompt.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/create_branch_from_ref_prompt.rs index 1ed64137..798abfb5 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/create_branch_from_ref_prompt.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/create_branch_from_ref_prompt.rs @@ -1,14 +1,5 @@ use super::*; -fn hotkey_hint(theme: AppTheme, debug_selector: &'static str, label: &'static str) -> gpui::Div { - div() - .debug_selector(move || debug_selector.to_string()) - .font_family(crate::font_preferences::EDITOR_MONOSPACE_FONT_FAMILY) - .text_xs() - .text_color(theme.colors.text_muted) - .child(label) -} - fn checkout_toggle( theme: AppTheme, enabled: bool, @@ -152,24 +143,10 @@ pub(super) fn panel( .flex() .flex_col() .w(scaled_px(540.0)) - .child( - div() - .px_2() - .py_1() - .text_sm() - .font_weight(FontWeight::BOLD) - .child("Create branch"), - ) + .child(popover_title("Create branch")) .child(div().border_t_1().border_color(theme.colors.border)) .child(source_row) - .child( - div() - .px_2() - .py_1() - .text_xs() - .text_color(theme.colors.text_muted) - .child("New branch name"), - ) + .child(input_label(theme, "New branch name")) .child( div() .px_2() @@ -199,11 +176,15 @@ pub(super) fn panel( .items_center() .justify_between() .child( - cancel_button("create_branch_from_ref_cancel", "create_branch_from_ref_cancel_hint", theme) - .focus_handle(this.create_branch_from_ref_cancel_focus_handle.clone()) - .on_click(theme, cx, |this, _e, window, cx| { - this.dismiss_prompt_popover(window, cx); - }), + cancel_button( + "create_branch_from_ref_cancel", + "create_branch_from_ref_cancel_hint", + theme, + ) + .focus_handle(this.create_branch_from_ref_cancel_focus_handle.clone()) + .on_click(theme, cx, |this, _e, window, cx| { + this.dismiss_prompt_popover(window, cx); + }), ) .child( components::Button::new("create_branch_from_ref_go", "Create") diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/create_tag_prompt.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/create_tag_prompt.rs index 6b76930d..32a63a2e 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/create_tag_prompt.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/create_tag_prompt.rs @@ -68,14 +68,7 @@ pub(super) fn panel( .flex() .flex_col() .w(scaled_px(420.0)) - .child( - div() - .px_2() - .py_1() - .text_sm() - .font_weight(FontWeight::BOLD) - .child("Create tag"), - ) + .child(popover_title("Create tag")) .child(div().border_t_1().border_color(theme.colors.border)) .child( div() diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/delete_remote_branch_confirm.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/delete_remote_branch_confirm.rs index 2be6b476..a5b676b1 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/delete_remote_branch_confirm.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/delete_remote_branch_confirm.rs @@ -16,14 +16,7 @@ pub(super) fn panel( .flex() .flex_col() .min_w(scaled_px(420.0)) - .child( - div() - .px_2() - .py_1() - .text_sm() - .font_weight(FontWeight::BOLD) - .child("Delete remote branch?"), - ) + .child(popover_title("Delete remote branch?")) .child(div().border_t_1().border_color(theme.colors.border)) .child( div().px_2().py_1().text_sm().child( @@ -59,12 +52,16 @@ pub(super) fn panel( .items_center() .justify_between() .child( - cancel_button("delete_remote_branch_cancel", "delete_remote_branch_cancel_hint", theme) - .on_click(theme, cx, |this, _e, _w, cx| { - this.popover = None; - this.popover_anchor = None; - cx.notify(); - }), + cancel_button( + "delete_remote_branch_cancel", + "delete_remote_branch_cancel_hint", + theme, + ) + .on_click(theme, cx, |this, _e, _w, cx| { + this.popover = None; + this.popover_anchor = None; + cx.notify(); + }), ) .child( components::Button::new("delete_remote_branch_go", "Delete") diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/discard_changes_confirm.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/discard_changes_confirm.rs index 94d8acf9..32f02e74 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/discard_changes_confirm.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/discard_changes_confirm.rs @@ -68,14 +68,7 @@ pub(super) fn panel( .flex() .flex_col() .min_w(scaled_px(420.0)) - .child( - div() - .px_2() - .py_1() - .text_sm() - .font_weight(FontWeight::BOLD) - .child("Discard changes"), - ) + .child(popover_title("Discard changes")) .child(div().border_t_1().border_color(theme.colors.border)) .child( div() @@ -96,12 +89,16 @@ pub(super) fn panel( .items_center() .justify_between() .child( - cancel_button("discard_changes_cancel", "discard_changes_cancel_hint", theme) - .on_click(theme, cx, |this, _e, _w, cx| { - this.popover = None; - this.popover_anchor = None; - cx.notify(); - }), + cancel_button( + "discard_changes_cancel", + "discard_changes_cancel_hint", + theme, + ) + .on_click(theme, cx, |this, _e, _w, cx| { + this.popover = None; + this.popover_anchor = None; + cx.notify(); + }), ) .child( components::Button::new("discard_changes_go", "Discard") diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/force_delete_branch_confirm.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/force_delete_branch_confirm.rs index 24668524..e4fe866f 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/force_delete_branch_confirm.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/force_delete_branch_confirm.rs @@ -14,14 +14,7 @@ pub(super) fn panel( .flex() .flex_col() .min_w(scaled_px(420.0)) - .child( - div() - .px_2() - .py_1() - .text_sm() - .font_weight(FontWeight::BOLD) - .child("Delete branch anyway?"), - ) + .child(popover_title("Delete branch anyway?")) .child(div().border_t_1().border_color(theme.colors.border)) .child(div().px_2().py_1().text_sm().child( div() diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/force_push_confirm.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/force_push_confirm.rs index f70bf9fd..dfcb819f 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/force_push_confirm.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/force_push_confirm.rs @@ -40,14 +40,7 @@ pub(super) fn panel( .flex() .flex_col() .min_w(scaled_px(420.0)) - .child( - div() - .px_2() - .py_1() - .text_sm() - .font_weight(FontWeight::BOLD) - .child("Force push"), - ) + .child(popover_title("Force push")) .child(div().border_t_1().border_color(theme.colors.border)) .child( div() @@ -75,12 +68,15 @@ pub(super) fn panel( .items_center() .justify_between() .child( - cancel_button("force_push_cancel", "force_push_cancel_hint", theme) - .on_click(theme, cx, |this, _e, _w, cx| { + cancel_button("force_push_cancel", "force_push_cancel_hint", theme).on_click( + theme, + cx, + |this, _e, _w, cx| { this.popover = None; this.popover_anchor = None; cx.notify(); - }), + }, + ), ) .child( components::Button::new("force_push_go", button_label) diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/force_remove_worktree_confirm.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/force_remove_worktree_confirm.rs index ae87d0e3..acea420b 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/force_remove_worktree_confirm.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/force_remove_worktree_confirm.rs @@ -28,14 +28,7 @@ pub(super) fn panel( .flex() .flex_col() .min_w(scaled_px(460.0)) - .child( - div() - .px_2() - .py_1() - .text_sm() - .font_weight(FontWeight::BOLD) - .child(header), - ) + .child(popover_title(header)) .child(div().border_t_1().border_color(theme.colors.border)) .child( div() @@ -71,12 +64,16 @@ pub(super) fn panel( .items_center() .justify_between() .child( - cancel_button("force_remove_worktree_cancel", "force_remove_worktree_cancel_hint", theme) - .on_click(theme, cx, |this, _e, _w, cx| { - this.popover = None; - this.popover_anchor = None; - cx.notify(); - }), + cancel_button( + "force_remove_worktree_cancel", + "force_remove_worktree_cancel_hint", + theme, + ) + .on_click(theme, cx, |this, _e, _w, cx| { + this.popover = None; + this.popover_anchor = None; + cx.notify(); + }), ) .child( components::Button::new("force_remove_worktree_go", "Delete anyway") diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/merge_abort_confirm.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/merge_abort_confirm.rs index e1cd7bfa..3272b9fd 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/merge_abort_confirm.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/merge_abort_confirm.rs @@ -51,14 +51,7 @@ pub(super) fn panel( .flex() .flex_col() .min_w(scaled_px(360.0)) - .child( - div() - .px_2() - .py_1() - .text_sm() - .font_weight(FontWeight::BOLD) - .child(title), - ) + .child(popover_title(title)) .child(div().border_t_1().border_color(theme.colors.border)) .child( div() @@ -86,12 +79,15 @@ pub(super) fn panel( .items_center() .justify_between() .child( - cancel_button("merge_abort_cancel", "merge_abort_cancel_hint", theme) - .on_click(theme, cx, |this, _e, _w, cx| { + cancel_button("merge_abort_cancel", "merge_abort_cancel_hint", theme).on_click( + theme, + cx, + |this, _e, _w, cx| { this.popover = None; this.popover_anchor = None; cx.notify(); - }), + }, + ), ) .child( components::Button::new(button_id, button_label) diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/pull_reconcile_prompt.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/pull_reconcile_prompt.rs index 56120859..75a14184 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/pull_reconcile_prompt.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/pull_reconcile_prompt.rs @@ -13,14 +13,7 @@ pub(super) fn panel( .flex() .flex_col() .min_w(scaled_px(440.0)) - .child( - div() - .px_2() - .py_1() - .text_sm() - .font_weight(FontWeight::BOLD) - .child("Pull: choose strategy"), - ) + .child(popover_title("Pull: choose strategy")) .child(div().border_t_1().border_color(theme.colors.border)) .child( div() diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/push_set_upstream_prompt.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/push_set_upstream_prompt.rs index 9d2868ab..d8c84310 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/push_set_upstream_prompt.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/push_set_upstream_prompt.rs @@ -15,14 +15,7 @@ pub(super) fn panel( .flex() .flex_col() .w(scaled_px(320.0)) - .child( - div() - .px_2() - .py_1() - .text_sm() - .font_weight(FontWeight::BOLD) - .child("Set upstream and push"), - ) + .child(popover_title("Set upstream and push")) .child(div().border_t_1().border_color(theme.colors.border)) .child( div() diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/remote_add_prompt.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/remote_add_prompt.rs index 92531792..7a3d9927 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/remote_add_prompt.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/remote_add_prompt.rs @@ -13,23 +13,9 @@ pub(super) fn panel( .flex() .flex_col() .w(scaled_px(640.0)) - .child( - div() - .px_2() - .py_1() - .text_sm() - .font_weight(FontWeight::BOLD) - .child("Add remote"), - ) + .child(popover_title("Add remote")) .child(div().border_t_1().border_color(theme.colors.border)) - .child( - div() - .px_2() - .py_1() - .text_xs() - .text_color(theme.colors.text_muted) - .child("Name"), - ) + .child(input_label(theme, "Name")) .child( div() .px_2() @@ -38,14 +24,7 @@ pub(super) fn panel( .min_w(px(0.0)) .child(this.remote_name_input.clone()), ) - .child( - div() - .px_2() - .py_1() - .text_xs() - .text_color(theme.colors.text_muted) - .child("URL"), - ) + .child(input_label(theme, "URL")) .child( div() .px_2() diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/remote_edit_url_prompt.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/remote_edit_url_prompt.rs index 593920cf..2102231a 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/remote_edit_url_prompt.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/remote_edit_url_prompt.rs @@ -19,14 +19,7 @@ pub(super) fn panel( .flex() .flex_col() .w(scaled_px(640.0)) - .child( - div() - .px_2() - .py_1() - .text_sm() - .font_weight(FontWeight::BOLD) - .child(format!("Edit remote URL ({kind_label})")), - ) + .child(popover_title(format!("Edit remote URL ({kind_label})"))) .child(div().border_t_1().border_color(theme.colors.border)) .child( div() @@ -53,11 +46,15 @@ pub(super) fn panel( .items_center() .justify_between() .child( - cancel_button("edit_remote_url_cancel", "edit_remote_url_cancel_hint", theme) - .focus_handle(this.remote_edit_cancel_focus_handle.clone()) - .on_click(theme, cx, |this, _e, window, cx| { - this.dismiss_prompt_popover(window, cx); - }), + cancel_button( + "edit_remote_url_cancel", + "edit_remote_url_cancel_hint", + theme, + ) + .focus_handle(this.remote_edit_cancel_focus_handle.clone()) + .on_click(theme, cx, |this, _e, window, cx| { + this.dismiss_prompt_popover(window, cx); + }), ) .child( components::Button::new("edit_remote_url_go", "Save") diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/remote_remove_confirm.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/remote_remove_confirm.rs index 09cc7af0..c7c26551 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/remote_remove_confirm.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/remote_remove_confirm.rs @@ -14,14 +14,7 @@ pub(super) fn panel( .flex() .flex_col() .min_w(scaled_px(420.0)) - .child( - div() - .px_2() - .py_1() - .text_sm() - .font_weight(FontWeight::BOLD) - .child("Remove remote"), - ) + .child(popover_title("Remove remote")) .child(div().border_t_1().border_color(theme.colors.border)) .child( div() diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/reset_prompt.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/reset_prompt.rs index 6679c741..4e1434cf 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/reset_prompt.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/reset_prompt.rs @@ -20,14 +20,7 @@ pub(super) fn panel( .flex() .flex_col() .min_w(scaled_px(380.0)) - .child( - div() - .px_2() - .py_1() - .text_sm() - .font_weight(FontWeight::BOLD) - .child("Reset"), - ) + .child(popover_title("Reset")) .child(div().border_t_1().border_color(theme.colors.border)) .child( div() @@ -58,12 +51,15 @@ pub(super) fn panel( .items_center() .justify_between() .child( - cancel_button("reset_cancel", "reset_cancel_hint", theme) - .on_click(theme, cx, |this, _e, _w, cx| { + cancel_button("reset_cancel", "reset_cancel_hint", theme).on_click( + theme, + cx, + |this, _e, _w, cx| { this.popover = None; this.popover_anchor = None; cx.notify(); - }), + }, + ), ) .child( components::Button::new("reset_go", "Reset") diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/stash_drop_confirm.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/stash_drop_confirm.rs index c2e24273..0b6071a5 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/stash_drop_confirm.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/stash_drop_confirm.rs @@ -21,14 +21,7 @@ pub(super) fn panel( .flex() .flex_col() .min_w(scaled_px(420.0)) - .child( - div() - .px_2() - .py_1() - .text_sm() - .font_weight(FontWeight::BOLD) - .child("Drop stash?"), - ) + .child(popover_title("Drop stash?")) .child(div().border_t_1().border_color(theme.colors.border)) .child( div().px_2().py_1().text_sm().child( diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/stash_picker_prompt.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/stash_picker_prompt.rs index d04001b2..345aa3f3 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/stash_picker_prompt.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/stash_picker_prompt.rs @@ -20,14 +20,7 @@ pub(super) fn panel( .flex() .flex_col() .w(scaled_px(420.0)) - .child( - div() - .px_2() - .py_1() - .text_sm() - .font_weight(FontWeight::BOLD) - .child(title), - ) + .child(popover_title(title)) .child(div().border_t_1().border_color(theme.colors.border)); if let Some(search) = this.stash_picker_search_input.clone() { diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/stash_prompt.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/stash_prompt.rs index 0a53157b..5132500c 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/stash_prompt.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/stash_prompt.rs @@ -10,14 +10,7 @@ pub(super) fn panel(this: &mut PopoverHost, cx: &mut gpui::Context) .flex() .flex_col() .w(scaled_px(420.0)) - .child( - div() - .px_2() - .py_1() - .text_sm() - .font_weight(FontWeight::BOLD) - .child("Create stash"), - ) + .child(popover_title("Create stash")) .child(div().border_t_1().border_color(theme.colors.border)) .child( div() diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/submodule_add_prompt.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/submodule_add_prompt.rs index aad9a98d..410cbcc0 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/submodule_add_prompt.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/submodule_add_prompt.rs @@ -70,23 +70,9 @@ pub(super) fn panel( .flex() .flex_col() .w(scaled_px(640.0)) - .child( - div() - .px_2() - .py_1() - .text_sm() - .font_weight(FontWeight::BOLD) - .child("Add submodule"), - ) + .child(popover_title("Add submodule")) .child(div().border_t_1().border_color(theme.colors.border)) - .child( - div() - .px_2() - .py_1() - .text_xs() - .text_color(theme.colors.text_muted) - .child("URL"), - ) + .child(input_label(theme, "URL")) .child( div() .px_2() @@ -95,14 +81,7 @@ pub(super) fn panel( .min_w(px(0.0)) .child(this.submodule_url_input.clone()), ) - .child( - div() - .px_2() - .py_1() - .text_xs() - .text_color(theme.colors.text_muted) - .child("Path (relative)"), - ) + .child(input_label(theme, "Path (relative)")) .child( div() .px_2() @@ -111,14 +90,7 @@ pub(super) fn panel( .min_w(px(0.0)) .child(this.submodule_path_input.clone()), ) - .child( - div() - .px_2() - .py_1() - .text_xs() - .text_color(theme.colors.text_muted) - .child("Branch (optional)"), - ) + .child(input_label(theme, "Branch (optional)")) .child( div() .px_2() @@ -141,14 +113,7 @@ pub(super) fn panel( ) .when(advanced_expanded, |this_panel| { this_panel - .child( - div() - .px_2() - .py_1() - .text_xs() - .text_color(theme.colors.text_muted) - .child("Logical name (optional)"), - ) + .child(input_label(theme, "Logical name (optional)")) .child( div() .px_2() diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/submodule_change_pointer_prompt.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/submodule_change_pointer_prompt.rs index d8577d9e..e7fd5088 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/submodule_change_pointer_prompt.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/submodule_change_pointer_prompt.rs @@ -15,14 +15,7 @@ pub(super) fn panel( .flex() .flex_col() .w(scaled_px(420.0)) - .child( - div() - .px_2() - .py_1() - .text_sm() - .font_weight(FontWeight::BOLD) - .child("Change submodule pointer"), - ) + .child(popover_title("Change submodule pointer")) .child(div().border_t_1().border_color(theme.colors.border)) .child( div() @@ -32,14 +25,7 @@ pub(super) fn panel( .text_color(theme.colors.text_muted) .child(format!("Submodule: {}", path.display())), ) - .child( - div() - .px_2() - .py_1() - .text_xs() - .text_color(theme.colors.text_muted) - .child("Target ref / branch / tag / commit"), - ) + .child(input_label(theme, "Target ref / branch / tag / commit")) .child( div() .px_2() @@ -57,10 +43,14 @@ pub(super) fn panel( .items_center() .justify_between() .child( - cancel_button("submodule_change_pointer_cancel", "submodule_change_pointer_cancel_hint", theme) - .on_click(theme, cx, |this, _e, window, cx| { - this.dismiss_inline_popover(window, cx); - }), + cancel_button( + "submodule_change_pointer_cancel", + "submodule_change_pointer_cancel_hint", + theme, + ) + .on_click(theme, cx, |this, _e, window, cx| { + this.dismiss_inline_popover(window, cx); + }), ) .child( components::Button::new("submodule_change_pointer_go", "Change") diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/submodule_remove_confirm.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/submodule_remove_confirm.rs index 677a169f..d4c7fa61 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/submodule_remove_confirm.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/submodule_remove_confirm.rs @@ -14,14 +14,7 @@ pub(super) fn panel( .flex() .flex_col() .min_w(scaled_px(420.0)) - .child( - div() - .px_2() - .py_1() - .text_sm() - .font_weight(FontWeight::BOLD) - .child("Remove submodule"), - ) + .child(popover_title("Remove submodule")) .child(div().border_t_1().border_color(theme.colors.border)) .child( div() @@ -40,12 +33,16 @@ pub(super) fn panel( .items_center() .justify_between() .child( - cancel_button("submodule_remove_cancel", "submodule_remove_cancel_hint", theme) - .on_click(theme, cx, |this, _e, _w, cx| { - this.popover = None; - this.popover_anchor = None; - cx.notify(); - }), + cancel_button( + "submodule_remove_cancel", + "submodule_remove_cancel_hint", + theme, + ) + .on_click(theme, cx, |this, _e, _w, cx| { + this.popover = None; + this.popover_anchor = None; + cx.notify(); + }), ) .child( components::Button::new("submodule_remove_go", "Remove") diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/submodule_trust_confirm.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/submodule_trust_confirm.rs index 43c20cc7..12560789 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/submodule_trust_confirm.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/submodule_trust_confirm.rs @@ -52,14 +52,7 @@ pub(super) fn panel( .flex() .flex_col() .w(scaled_px(640.0)) - .child( - div() - .px_2() - .py_1() - .text_sm() - .font_weight(FontWeight::BOLD) - .child(title), - ) + .child(popover_title(title)) .child(div().border_t_1().border_color(theme.colors.border)) .child( div() diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/terminal_shutdown_confirm.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/terminal_shutdown_confirm.rs index 9477c7d7..06e4ce89 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/terminal_shutdown_confirm.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/terminal_shutdown_confirm.rs @@ -45,14 +45,7 @@ pub(super) fn panel( .flex() .flex_col() .min_w(px(440.0)) - .child( - div() - .px_2() - .py_1() - .text_sm() - .font_weight(FontWeight::BOLD) - .child(title), - ) + .child(popover_title(title)) .child(div().border_t_1().border_color(theme.colors.border)) .child( div() @@ -95,14 +88,18 @@ pub(super) fn panel( .items_center() .justify_between() .child( - cancel_button("terminal_shutdown_cancel", "terminal_shutdown_cancel_hint", theme) - .on_click(theme, cx, |this, _e, _window, cx| { - let root_view = this.root_view.clone(); - let _ = root_view.update(cx, |root, cx| { - root.clear_pending_terminal_shutdown_prompt(cx); - }); - this.close_popover(cx); - }), + cancel_button( + "terminal_shutdown_cancel", + "terminal_shutdown_cancel_hint", + theme, + ) + .on_click(theme, cx, |this, _e, _window, cx| { + let root_view = this.root_view.clone(); + let _ = root_view.update(cx, |root, cx| { + root.clear_pending_terminal_shutdown_prompt(cx); + }); + this.close_popover(cx); + }), ) .child( components::Button::new("terminal_shutdown_confirm", confirm_label) diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/tests/dialog.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/tests/dialog.rs new file mode 100644 index 00000000..84a4ab75 --- /dev/null +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/tests/dialog.rs @@ -0,0 +1,269 @@ +use super::*; + +fn open_popover_and_draw( + view: &gpui::Entity, + kind: PopoverKind, + cx: &mut gpui::VisualTestContext, +) { + cx.update(|window, app| { + view.update(app, |this, cx| { + this.popover_host.update(cx, |host, cx| { + host.open_popover_at( + kind, + gpui::point(gpui::px(120.0), gpui::px(72.0)), + window, + cx, + ); + }); + }); + }); + cx.update(|window, app| { + let _ = window.draw(app); + }); +} + +fn assert_popover_open(view: &gpui::Entity, app: &gpui::App, expected: bool) { + let is_open = view.read(app).popover_host.read(app).is_open(); + assert_eq!(is_open, expected); +} + +// ── Category 1: Esc hint renders on Cancel buttons ── + +#[gpui::test] +fn force_push_confirm_renders_cancel_hint(cx: &mut gpui::TestAppContext) { + let (store, events) = AppStore::new(Arc::new(TestBackend)); + let (view, mut cx) = + cx.add_window_view(|window, cx| GitCometView::new(store, events, None, window, cx)); + cx.update(|window, app| { + crate::app::bind_text_input_keys_for_test(app); + let _ = window.draw(app); + }); + + open_popover_and_draw( + &view, + PopoverKind::ForcePushConfirm { repo_id: RepoId(1) }, + &mut cx, + ); + cx.debug_bounds("force_push_cancel_hint") + .expect("expected force push Cancel shortcut hint"); +} + +#[gpui::test] +fn stash_prompt_renders_cancel_hint(cx: &mut gpui::TestAppContext) { + let (store, events) = AppStore::new(Arc::new(TestBackend)); + let (view, mut cx) = + cx.add_window_view(|window, cx| GitCometView::new(store, events, None, window, cx)); + cx.update(|window, app| { + crate::app::bind_text_input_keys_for_test(app); + let _ = window.draw(app); + }); + + open_popover_and_draw(&view, PopoverKind::StashPrompt, &mut cx); + cx.debug_bounds("stash_cancel_hint") + .expect("expected stash Cancel shortcut hint"); +} + +#[gpui::test] +fn reset_prompt_renders_cancel_hint(cx: &mut gpui::TestAppContext) { + let (store, events) = AppStore::new(Arc::new(TestBackend)); + let (view, mut cx) = + cx.add_window_view(|window, cx| GitCometView::new(store, events, None, window, cx)); + cx.update(|window, app| { + crate::app::bind_text_input_keys_for_test(app); + let _ = window.draw(app); + }); + + open_popover_and_draw( + &view, + PopoverKind::ResetPrompt { + repo_id: RepoId(1), + target: "HEAD".to_string(), + mode: ResetMode::Mixed, + }, + &mut cx, + ); + cx.debug_bounds("reset_cancel_hint") + .expect("expected reset Cancel shortcut hint"); +} + +// ── Category 2: Esc dismisses popovers ── + +#[gpui::test] +fn force_push_confirm_escape_closes(cx: &mut gpui::TestAppContext) { + let (store, events) = AppStore::new(Arc::new(TestBackend)); + let (view, mut cx) = + cx.add_window_view(|window, cx| GitCometView::new(store, events, None, window, cx)); + cx.update(|window, app| { + crate::app::bind_text_input_keys_for_test(app); + let _ = window.draw(app); + }); + + open_popover_and_draw( + &view, + PopoverKind::ForcePushConfirm { repo_id: RepoId(1) }, + &mut cx, + ); + cx.update(|_window, app| assert_popover_open(&view, app, true)); + cx.simulate_keystrokes("escape"); + cx.run_until_parked(); + cx.update(|window, app| { + let _ = window.draw(app); + assert_popover_open(&view, app, false); + }); +} + +#[gpui::test] +fn stash_prompt_escape_closes(cx: &mut gpui::TestAppContext) { + let (store, events) = AppStore::new(Arc::new(TestBackend)); + let (view, mut cx) = + cx.add_window_view(|window, cx| GitCometView::new(store, events, None, window, cx)); + cx.update(|window, app| { + crate::app::bind_text_input_keys_for_test(app); + let _ = window.draw(app); + }); + + open_popover_and_draw(&view, PopoverKind::StashPrompt, &mut cx); + cx.update(|_window, app| assert_popover_open(&view, app, true)); + cx.simulate_keystrokes("escape"); + cx.run_until_parked(); + cx.update(|window, app| { + let _ = window.draw(app); + assert_popover_open(&view, app, false); + }); +} + +#[gpui::test] +fn reset_prompt_escape_closes(cx: &mut gpui::TestAppContext) { + let (store, events) = AppStore::new(Arc::new(TestBackend)); + let (view, mut cx) = + cx.add_window_view(|window, cx| GitCometView::new(store, events, None, window, cx)); + cx.update(|window, app| { + crate::app::bind_text_input_keys_for_test(app); + let _ = window.draw(app); + }); + + open_popover_and_draw( + &view, + PopoverKind::ResetPrompt { + repo_id: RepoId(1), + target: "HEAD".to_string(), + mode: ResetMode::Mixed, + }, + &mut cx, + ); + cx.update(|_window, app| assert_popover_open(&view, app, true)); + cx.simulate_keystrokes("escape"); + cx.run_until_parked(); + cx.update(|window, app| { + let _ = window.draw(app); + assert_popover_open(&view, app, false); + }); +} + +#[gpui::test] +fn pull_reconcile_prompt_escape_closes(cx: &mut gpui::TestAppContext) { + let (store, events) = AppStore::new(Arc::new(TestBackend)); + let (view, mut cx) = + cx.add_window_view(|window, cx| GitCometView::new(store, events, None, window, cx)); + cx.update(|window, app| { + crate::app::bind_text_input_keys_for_test(app); + let _ = window.draw(app); + }); + + open_popover_and_draw( + &view, + PopoverKind::PullReconcilePrompt { repo_id: RepoId(1) }, + &mut cx, + ); + cx.update(|_window, app| assert_popover_open(&view, app, true)); + cx.simulate_keystrokes("escape"); + cx.run_until_parked(); + cx.update(|window, app| { + let _ = window.draw(app); + assert_popover_open(&view, app, false); + }); +} + +#[gpui::test] +fn terminal_shutdown_confirm_escape_closes(cx: &mut gpui::TestAppContext) { + let (store, events) = AppStore::new(Arc::new(TestBackend)); + let (view, mut cx) = + cx.add_window_view(|window, cx| GitCometView::new(store, events, None, window, cx)); + cx.update(|window, app| { + crate::app::bind_text_input_keys_for_test(app); + let _ = window.draw(app); + }); + + open_popover_and_draw( + &view, + PopoverKind::TerminalShutdownConfirm(TerminalShutdownPrompt { + action: TerminalShutdownAction::CloseWindow, + summary: TerminalShutdownSummary::default(), + }), + &mut cx, + ); + cx.update(|_window, app| assert_popover_open(&view, app, true)); + cx.simulate_keystrokes("escape"); + cx.run_until_parked(); + cx.update(|window, app| { + let _ = window.draw(app); + assert_popover_open(&view, app, false); + }); +} + +#[gpui::test] +fn discard_changes_confirm_escape_closes(cx: &mut gpui::TestAppContext) { + let (store, events) = AppStore::new(Arc::new(TestBackend)); + let (view, mut cx) = + cx.add_window_view(|window, cx| GitCometView::new(store, events, None, window, cx)); + cx.update(|window, app| { + crate::app::bind_text_input_keys_for_test(app); + let _ = window.draw(app); + }); + + open_popover_and_draw( + &view, + PopoverKind::DiscardChangesConfirm { + repo_id: RepoId(1), + area: DiffArea::Unstaged, + path: None, + }, + &mut cx, + ); + cx.update(|_window, app| assert_popover_open(&view, app, true)); + cx.simulate_keystrokes("escape"); + cx.run_until_parked(); + cx.update(|window, app| { + let _ = window.draw(app); + assert_popover_open(&view, app, false); + }); +} + +#[gpui::test] +fn submodule_change_pointer_escape_closes(cx: &mut gpui::TestAppContext) { + let (store, events) = AppStore::new(Arc::new(TestBackend)); + let (view, mut cx) = + cx.add_window_view(|window, cx| GitCometView::new(store, events, None, window, cx)); + cx.update(|window, app| { + crate::app::bind_text_input_keys_for_test(app); + let _ = window.draw(app); + }); + + open_popover_and_draw( + &view, + PopoverKind::Repo { + repo_id: RepoId(1), + kind: RepoPopoverKind::Submodule(SubmodulePopoverKind::ChangePointerPrompt { + path: std::path::PathBuf::from("."), + }), + }, + &mut cx, + ); + cx.update(|_window, app| assert_popover_open(&view, app, true)); + cx.simulate_keystrokes("escape"); + cx.run_until_parked(); + cx.update(|window, app| { + let _ = window.draw(app); + assert_popover_open(&view, app, false); + }); +} diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/tests/mod.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/tests/mod.rs index 82b968d2..338f7ec2 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/tests/mod.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/tests/mod.rs @@ -51,6 +51,7 @@ mod branch; mod browse_history; mod clone; mod context_shortcuts; +mod dialog; mod file_actions; mod layout; mod picker; diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/worktree_add_prompt.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/worktree_add_prompt.rs index 54b70947..1d1521d2 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/worktree_add_prompt.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/worktree_add_prompt.rs @@ -74,23 +74,9 @@ pub(super) fn panel( .flex() .flex_col() .w(scaled_px(640.0)) - .child( - div() - .px_2() - .py_1() - .text_sm() - .font_weight(FontWeight::BOLD) - .child("Add worktree"), - ) + .child(popover_title("Add worktree")) .child(div().border_t_1().border_color(theme.colors.border)) - .child( - div() - .px_2() - .py_1() - .text_xs() - .text_color(theme.colors.text_muted) - .child("Worktree folder"), - ) + .child(input_label(theme, "Worktree folder")) .child( div() .px_2() diff --git a/crates/gitcomet-ui-gpui/src/view/panels/popover/worktree_remove_confirm.rs b/crates/gitcomet-ui-gpui/src/view/panels/popover/worktree_remove_confirm.rs index 05cdb46b..0281704c 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/popover/worktree_remove_confirm.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/popover/worktree_remove_confirm.rs @@ -25,14 +25,7 @@ pub(super) fn panel( .flex() .flex_col() .min_w(scaled_px(420.0)) - .child( - div() - .px_2() - .py_1() - .text_sm() - .font_weight(FontWeight::BOLD) - .child(header), - ) + .child(popover_title(header)) .child(div().border_t_1().border_color(theme.colors.border)) .child( div() @@ -62,12 +55,16 @@ pub(super) fn panel( .items_center() .justify_between() .child( - cancel_button("worktree_remove_cancel", "worktree_remove_cancel_hint", theme) - .on_click(theme, cx, |this, _e, _w, cx| { - this.popover = None; - this.popover_anchor = None; - cx.notify(); - }), + cancel_button( + "worktree_remove_cancel", + "worktree_remove_cancel_hint", + theme, + ) + .on_click(theme, cx, |this, _e, _w, cx| { + this.popover = None; + this.popover_anchor = None; + cx.notify(); + }), ) .child( components::Button::new("worktree_remove_go", "Remove") From 2f06c0404f9d13414ce3ca36e2ca8675a76d3e76 Mon Sep 17 00:00:00 2001 From: Roope Airinen Date: Mon, 6 Jul 2026 09:07:23 +0300 Subject: [PATCH 3/3] add description to commit pane details --- .../src/view/panels/layout.rs | 186 ++++++++++++------ .../src/view/panels/tests/file_status.rs | 10 +- 2 files changed, 132 insertions(+), 64 deletions(-) diff --git a/crates/gitcomet-ui-gpui/src/view/panels/layout.rs b/crates/gitcomet-ui-gpui/src/view/panels/layout.rs index 72e715dd..b70d88eb 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/layout.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/layout.rs @@ -41,6 +41,18 @@ fn commit_details_monospace_element(value: AnyElement) -> AnyElement { .into_any_element() } +fn split_commit_subject_body(message: &str) -> (&str, &str) { + let trimmed = message.trim(); + if let Some(newline_pos) = trimmed.find('\n') { + let subject = trimmed[..newline_pos].trim_end(); + let body = trimmed[newline_pos + 1..] + .trim_start_matches(|c: char| c == '\n' || c == '\r'); + (subject, body) + } else { + (trimmed, "") + } +} + fn commit_sha_link_style(theme: AppTheme) -> gpui::HighlightStyle { gpui::HighlightStyle { color: Some(theme.colors.accent.into()), @@ -554,10 +566,11 @@ impl DetailsPaneView { repo_id: RepoId, cx: &mut gpui::Context, ) { - let (highlights, links) = commit_message_sha_highlights(message, theme); + let (_subject, body) = split_commit_subject_body(message); + let (highlights, links) = commit_message_sha_highlights(body, theme); self.commit_details_message_input.update(cx, |input, cx| { - if input.text() != message { - input.set_text(message.to_string(), cx); + if input.text() != body { + input.set_text(body.to_string(), cx); } input.set_highlights(highlights, cx); }); @@ -645,9 +658,10 @@ impl DetailsPaneView { message: &str, cx: &mut gpui::Context, ) { + let (_subject, body) = split_commit_subject_body(message); self.commit_details_message_input.update(cx, |input, cx| { - if input.text() != message { - input.set_text(message.to_string(), cx); + if input.text() != body { + input.set_text(body.to_string(), cx); } input.set_highlights(Vec::new(), cx); }); @@ -834,36 +848,63 @@ impl DetailsPaneView { cx, ); - let message = div() - .id(("commit_details_message_container", repo_id.0)) - .relative() + let (subject, body) = split_commit_subject_body(details.message.as_str()); + + let subject_label = div() .w_full() .min_w(px(0.0)) - .child(restrict_scroll_to_vertical_axis( - div() - .id(("commit_details_message_scroll_surface", repo_id.0)) - .debug_selector(|| { - "commit_details_message_scroll_surface".to_string() - }) - .relative() - .w_full() - .min_w(px(0.0)) - .max_h(px(COMMIT_DETAILS_MESSAGE_MAX_HEIGHT_PX)) - .pr(components::Scrollbar::visible_gutter( - self.commit_scroll.clone(), - components::ScrollbarAxis::Vertical, - )) - .overflow_y_scroll() - .track_scroll(&self.commit_scroll) - .child(self.commit_details_message_sha_menu.clone()), - )) - .child( - components::Scrollbar::new( - ("commit_details_message_scrollbar", repo_id.0), - self.commit_scroll.clone(), + .font_weight(FontWeight::BOLD) + .child(subject.to_string()); + + let message: Div = if body.is_empty() { + subject_label + } else { + div() + .flex() + .flex_col() + .w_full() + .min_w(px(0.0)) + .child(subject_label) + .child( + div() + .w_full() + .border_t_1() + .border_color(theme.colors.border) + .my(px(4.0)), ) - .render(theme), - ); + .child( + div() + .id(("commit_details_message_container", repo_id.0)) + .relative() + .w_full() + .min_w(px(0.0)) + .child(restrict_scroll_to_vertical_axis( + div() + .id(("commit_details_message_scroll_surface", repo_id.0)) + .debug_selector(|| { + "commit_details_message_scroll_surface".to_string() + }) + .relative() + .w_full() + .min_w(px(0.0)) + .max_h(px(COMMIT_DETAILS_MESSAGE_MAX_HEIGHT_PX)) + .pr(components::Scrollbar::visible_gutter( + self.commit_scroll.clone(), + components::ScrollbarAxis::Vertical, + )) + .overflow_y_scroll() + .track_scroll(&self.commit_scroll) + .child(self.commit_details_message_sha_menu.clone()), + )) + .child( + components::Scrollbar::new( + ("commit_details_message_scrollbar", repo_id.0), + self.commit_scroll.clone(), + ) + .render(theme), + ), + ) + }; div() .flex() @@ -1010,36 +1051,63 @@ impl DetailsPaneView { cx, ); - let message = div() - .id(("commit_details_message_container", repo_id.0)) - .relative() + let (subject, body) = split_commit_subject_body(details.message.as_str()); + + let subject_label = div() .w_full() .min_w(px(0.0)) - .child(restrict_scroll_to_vertical_axis( - div() - .id(("commit_details_message_scroll_surface", repo_id.0)) - .debug_selector(|| { - "commit_details_message_scroll_surface".to_string() - }) - .relative() - .w_full() - .min_w(px(0.0)) - .max_h(px(COMMIT_DETAILS_MESSAGE_MAX_HEIGHT_PX)) - .pr(components::Scrollbar::visible_gutter( - self.commit_scroll.clone(), - components::ScrollbarAxis::Vertical, - )) - .overflow_y_scroll() - .track_scroll(&self.commit_scroll) - .child(self.commit_details_message_sha_menu.clone()), - )) - .child( - components::Scrollbar::new( - ("commit_details_message_scrollbar", repo_id.0), - self.commit_scroll.clone(), + .font_weight(FontWeight::BOLD) + .child(subject.to_string()); + + let message: Div = if body.is_empty() { + subject_label + } else { + div() + .flex() + .flex_col() + .w_full() + .min_w(px(0.0)) + .child(subject_label) + .child( + div() + .w_full() + .border_t_1() + .border_color(theme.colors.border) + .my(px(4.0)), ) - .render(theme), - ); + .child( + div() + .id(("commit_details_message_container", repo_id.0)) + .relative() + .w_full() + .min_w(px(0.0)) + .child(restrict_scroll_to_vertical_axis( + div() + .id(("commit_details_message_scroll_surface", repo_id.0)) + .debug_selector(|| { + "commit_details_message_scroll_surface".to_string() + }) + .relative() + .w_full() + .min_w(px(0.0)) + .max_h(px(COMMIT_DETAILS_MESSAGE_MAX_HEIGHT_PX)) + .pr(components::Scrollbar::visible_gutter( + self.commit_scroll.clone(), + components::ScrollbarAxis::Vertical, + )) + .overflow_y_scroll() + .track_scroll(&self.commit_scroll) + .child(self.commit_details_message_sha_menu.clone()), + )) + .child( + components::Scrollbar::new( + ("commit_details_message_scrollbar", repo_id.0), + self.commit_scroll.clone(), + ) + .render(theme), + ), + ) + }; div() .flex() diff --git a/crates/gitcomet-ui-gpui/src/view/panels/tests/file_status.rs b/crates/gitcomet-ui-gpui/src/view/panels/tests/file_status.rs index 13a09118..a04d4f42 100644 --- a/crates/gitcomet-ui-gpui/src/view/panels/tests/file_status.rs +++ b/crates/gitcomet-ui-gpui/src/view/panels/tests/file_status.rs @@ -1620,7 +1620,7 @@ fn commit_details_message_sha_hover_menu_navigate_reveals_referenced_commit( repo.history_state.commit_details = gitcomet_state::model::Loadable::Ready(Arc::new( gitcomet_core::domain::CommitDetails { id: gitcomet_core::domain::CommitId(current_sha.into()), - message: format!("{target_sha_upper} fixes the regression"), + message: format!("Fix regression\n\n{target_sha_upper} fixes the regression"), committed_at: "2026-03-08 12:34:56 +0200".into(), parent_ids: vec![], files: vec![], @@ -1720,7 +1720,7 @@ fn commit_details_message_sha_hover_menu_closes_after_leaving_trigger_and_menu( repo.history_state.commit_details = Loadable::Ready(Arc::new(gitcomet_core::domain::CommitDetails { id: gitcomet_core::domain::CommitId(current_sha.into()), - message: format!("{target_sha} fixes the regression"), + message: format!("Fix regression\n\n{target_sha} fixes the regression"), committed_at: "2026-03-08 12:34:56 +0200".into(), parent_ids: vec![], files: vec![], @@ -1830,7 +1830,7 @@ fn commit_details_message_sha_retained_details_are_inert_after_selection_changes repo.history_state.commit_details = gitcomet_state::model::Loadable::Ready(Arc::new( gitcomet_core::domain::CommitDetails { id: gitcomet_core::domain::CommitId(retained_sha.into()), - message: format!("{target_sha} should not reveal from retained details"), + message: format!("Retained details\n\n{target_sha} should not reveal from retained details"), committed_at: "2026-03-08 12:34:56 +0200".into(), parent_ids: vec![], files: vec![], @@ -1917,7 +1917,7 @@ fn commit_details_message_sha_left_click_only_places_caret_without_revealing( repo.history_state.commit_details = gitcomet_state::model::Loadable::Ready(Arc::new( gitcomet_core::domain::CommitDetails { id: gitcomet_core::domain::CommitId(current_sha.into()), - message: format!("{target_sha} fixes the regression"), + message: format!("Fix regression\n\n{target_sha} fixes the regression"), committed_at: "2026-03-08 12:34:56 +0200".into(), parent_ids: vec![], files: vec![], @@ -2002,7 +2002,7 @@ fn commit_details_message_sha_keeps_hover_menu_open_while_link_is_focused( repo.history_state.commit_details = gitcomet_state::model::Loadable::Ready(Arc::new( gitcomet_core::domain::CommitDetails { id: gitcomet_core::domain::CommitId(current_sha.into()), - message: format!("{target_sha} fixes the regression"), + message: format!("Fix regression\n\n{target_sha} fixes the regression"), committed_at: "2026-03-08 12:34:56 +0200".into(), parent_ids: vec![], files: vec![],