diff --git a/demo/Ursa.Demo/Pages/PopConfirmDemo.axaml b/demo/Ursa.Demo/Pages/PopConfirmDemo.axaml
new file mode 100644
index 0000000..dc10dee
--- /dev/null
+++ b/demo/Ursa.Demo/Pages/PopConfirmDemo.axaml
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/demo/Ursa.Demo/Pages/PopConfirmDemo.axaml.cs b/demo/Ursa.Demo/Pages/PopConfirmDemo.axaml.cs
new file mode 100644
index 0000000..5f9713b
--- /dev/null
+++ b/demo/Ursa.Demo/Pages/PopConfirmDemo.axaml.cs
@@ -0,0 +1,25 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+using Ursa.Controls;
+using Ursa.Demo.ViewModels;
+
+namespace Ursa.Demo.Pages;
+
+public partial class PopConfirmDemo : UserControl
+{
+ public PopConfirmDemo()
+ {
+ InitializeComponent();
+ }
+
+ protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
+ {
+ base.OnAttachedToVisualTree(e);
+ if (this.DataContext is not PopConfirmDemoViewModel vm) return;
+ var manager = WindowToastManager.TryGetToastManager(TopLevel.GetTopLevel(this), out var m)
+ ? m
+ : new WindowToastManager(TopLevel.GetTopLevel(this));
+ vm.ToastManager = manager;
+ }
+}
\ No newline at end of file
diff --git a/demo/Ursa.Demo/ViewModels/MainViewViewModel.cs b/demo/Ursa.Demo/ViewModels/MainViewViewModel.cs
index 181c82d..e591d80 100644
--- a/demo/Ursa.Demo/ViewModels/MainViewViewModel.cs
+++ b/demo/Ursa.Demo/ViewModels/MainViewViewModel.cs
@@ -69,6 +69,7 @@ public partial class MainViewViewModel : ViewModelBase
MenuKeys.MenuKeyNumPad => new NumPadDemoViewModel(),
MenuKeys.MenuKeyPagination => new PaginationDemoViewModel(),
MenuKeys.MenuKeyPinCode => new PinCodeDemoViewModel(),
+ MenuKeys.MenuKeyPopConfirm => new PopConfirmDemoViewModel(),
MenuKeys.MenuKeyRangeSlider => new RangeSliderDemoViewModel(),
MenuKeys.MenuKeyRating => new RatingDemoViewModel(),
MenuKeys.MenuKeyScrollToButton => new ScrollToButtonDemoViewModel(),
diff --git a/demo/Ursa.Demo/ViewModels/MenuViewModel.cs b/demo/Ursa.Demo/ViewModels/MenuViewModel.cs
index fde221b..7dfffbd 100644
--- a/demo/Ursa.Demo/ViewModels/MenuViewModel.cs
+++ b/demo/Ursa.Demo/ViewModels/MenuViewModel.cs
@@ -44,6 +44,7 @@ public class MenuViewModel : ViewModelBase
new() { MenuHeader = "Loading", Key = MenuKeys.MenuKeyLoading, Status = "Updated" },
new() { MenuHeader = "Message Box", Key = MenuKeys.MenuKeyMessageBox },
new() { MenuHeader = "Notification", Key = MenuKeys.MenuKeyNotification },
+ new() { MenuHeader = "PopConfirm", Key = MenuKeys.MenuKeyPopConfirm },
new() { MenuHeader = "Toast", Key = MenuKeys.MenuKeyToast },
new() { MenuHeader = "Skeleton", Key = MenuKeys.MenuKeySkeleton },
}
@@ -135,6 +136,7 @@ public static class MenuKeys
public const string MenuKeyNumPad = "NumPad";
public const string MenuKeyPagination = "Pagination";
public const string MenuKeyPinCode = "PinCode";
+ public const string MenuKeyPopConfirm = "PopConfirm";
public const string MenuKeyRangeSlider = "RangeSlider";
public const string MenuKeyRating = "Rating";
public const string MenuKeyScrollToButton = "ScrollToButton";
diff --git a/demo/Ursa.Demo/ViewModels/PopConfirmDemoViewModel.cs b/demo/Ursa.Demo/ViewModels/PopConfirmDemoViewModel.cs
new file mode 100644
index 0000000..925705a
--- /dev/null
+++ b/demo/Ursa.Demo/ViewModels/PopConfirmDemoViewModel.cs
@@ -0,0 +1,48 @@
+using System.Threading.Tasks;
+using System.Windows.Input;
+using Avalonia.Controls.Notifications;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using Ursa.Controls;
+
+namespace Ursa.Demo.ViewModels;
+
+public class PopConfirmDemoViewModel : ObservableObject
+{
+ public PopConfirmDemoViewModel()
+ {
+ AsyncConfirmCommand = new AsyncRelayCommand(OnConfirmAsync);
+ AsyncCancelCommand = new RelayCommand(OnCancelAsync);
+ ConfirmCommand = new RelayCommand(OnConfirm);
+ CancelCommand = new RelayCommand(OnCancel);
+ }
+
+ internal WindowToastManager? ToastManager { get; set; }
+
+ public ICommand ConfirmCommand { get; }
+ public ICommand CancelCommand { get; }
+
+ public ICommand AsyncConfirmCommand { get; }
+ public ICommand AsyncCancelCommand { get; }
+
+ private void OnCancel()
+ {
+ ToastManager?.Show(new Toast("Canceled"), NotificationType.Error, classes: ["Light"]);
+ }
+
+ private void OnConfirm()
+ {
+ ToastManager?.Show(new Toast("Confirmed"), NotificationType.Success, classes: ["Light"]);
+ }
+
+ private async Task OnConfirmAsync()
+ {
+ await Task.Delay(3000);
+ ToastManager?.Show(new Toast("Async Confirmed"), NotificationType.Success, classes: ["Light"]);
+ }
+
+ private void OnCancelAsync()
+ {
+ ToastManager?.Show(new Toast("Async Canceled"), NotificationType.Error, classes: ["Light"]);
+ }
+}
\ No newline at end of file
diff --git a/src/Ursa.Themes.Semi/Controls/PopConfirm.axaml b/src/Ursa.Themes.Semi/Controls/PopConfirm.axaml
new file mode 100644
index 0000000..6e0afb4
--- /dev/null
+++ b/src/Ursa.Themes.Semi/Controls/PopConfirm.axaml
@@ -0,0 +1,135 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Ursa.Themes.Semi/Controls/_index.axaml b/src/Ursa.Themes.Semi/Controls/_index.axaml
index ce51210..5b33542 100644
--- a/src/Ursa.Themes.Semi/Controls/_index.axaml
+++ b/src/Ursa.Themes.Semi/Controls/_index.axaml
@@ -36,26 +36,27 @@
+
+
+
+
+
-
-
-
-
diff --git a/src/Ursa.Themes.Semi/Themes/Dark/PopConfirm.axaml b/src/Ursa.Themes.Semi/Themes/Dark/PopConfirm.axaml
new file mode 100644
index 0000000..bc98383
--- /dev/null
+++ b/src/Ursa.Themes.Semi/Themes/Dark/PopConfirm.axaml
@@ -0,0 +1,6 @@
+
+ #43444A
+
+
+ inset 0 0 0 1 #1AFFFFFF, 0 4 14 #40000000
+
\ No newline at end of file
diff --git a/src/Ursa.Themes.Semi/Themes/Dark/_index.axaml b/src/Ursa.Themes.Semi/Themes/Dark/_index.axaml
index 723f977..0d5148a 100644
--- a/src/Ursa.Themes.Semi/Themes/Dark/_index.axaml
+++ b/src/Ursa.Themes.Semi/Themes/Dark/_index.axaml
@@ -15,6 +15,7 @@
+
diff --git a/src/Ursa.Themes.Semi/Themes/Light/PopConfirm.axaml b/src/Ursa.Themes.Semi/Themes/Light/PopConfirm.axaml
new file mode 100644
index 0000000..de092db
--- /dev/null
+++ b/src/Ursa.Themes.Semi/Themes/Light/PopConfirm.axaml
@@ -0,0 +1,6 @@
+
+ White
+
+
+ 0 0 1 #4A000000, 0 4 14 #1A000000
+
\ No newline at end of file
diff --git a/src/Ursa.Themes.Semi/Themes/Light/_index.axaml b/src/Ursa.Themes.Semi/Themes/Light/_index.axaml
index 723f977..0d5148a 100644
--- a/src/Ursa.Themes.Semi/Themes/Light/_index.axaml
+++ b/src/Ursa.Themes.Semi/Themes/Light/_index.axaml
@@ -15,6 +15,7 @@
+
diff --git a/src/Ursa.Themes.Semi/Themes/Shared/PopConfirm.axaml b/src/Ursa.Themes.Semi/Themes/Shared/PopConfirm.axaml
new file mode 100644
index 0000000..ed13d78
--- /dev/null
+++ b/src/Ursa.Themes.Semi/Themes/Shared/PopConfirm.axaml
@@ -0,0 +1,11 @@
+
+ 400
+ 20 24 24 24
+ 4
+ 1
+ 6
+ 0 0 12 0
+ 16
+ 600
+
\ No newline at end of file
diff --git a/src/Ursa.Themes.Semi/Themes/Shared/_index.axaml b/src/Ursa.Themes.Semi/Themes/Shared/_index.axaml
index 9d42c27..01c7e1a 100644
--- a/src/Ursa.Themes.Semi/Themes/Shared/_index.axaml
+++ b/src/Ursa.Themes.Semi/Themes/Shared/_index.axaml
@@ -16,8 +16,9 @@
+
-
+
diff --git a/src/Ursa/Controls/PopConfirm/PopConfirm.cs b/src/Ursa/Controls/PopConfirm/PopConfirm.cs
new file mode 100644
index 0000000..cd4c6b6
--- /dev/null
+++ b/src/Ursa/Controls/PopConfirm/PopConfirm.cs
@@ -0,0 +1,295 @@
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Windows.Input;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Controls.Metadata;
+using Avalonia.Controls.Presenters;
+using Avalonia.Controls.Primitives;
+using Avalonia.Controls.Templates;
+using Avalonia.Input;
+using Avalonia.Interactivity;
+using Avalonia.LogicalTree;
+using Irihi.Avalonia.Shared.Helpers;
+
+namespace Ursa.Controls;
+
+[PseudoClasses(PC_DropdownOpen, PC_Icon)]
+public class PopConfirm : ContentControl
+{
+ public const string PART_CloseButton = "PART_CloseButton";
+ public const string PART_ConfirmButton = "PART_ConfirmButton";
+ public const string PART_CancelButton = "PART_CancelButton";
+ public const string PART_Popup = "PART_Popup";
+ public const string PC_DropdownOpen = ":dropdownopen";
+ public const string PC_Icon = ":icon";
+
+ public static readonly StyledProperty