diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 6d6580874..440f1fbec 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -29,7 +29,7 @@
- [ ] Has samples (if omitted, state reason in description)
- [ ] Rebased on top of `main` at time of PR
- [ ] Changes adhere to [coding standard](https://github.com/CommunityToolkit/Maui/blob/main/CONTRIBUTING.md#contributing-code---best-practices)
- - [ ] Documentation created or updated: https://github.com/MicrosoftDocs/CommunityToolkit/pull/XYZ
+ - [ ] Documentation created or updated: https://github.com/MicrosoftDocs/CommunityToolkit/pulls
### Additional information ###
diff --git a/samples/CommunityToolkit.Maui.Sample/App.xaml b/samples/CommunityToolkit.Maui.Sample/App.xaml
index d7230b24e..a51300737 100644
--- a/samples/CommunityToolkit.Maui.Sample/App.xaml
+++ b/samples/CommunityToolkit.Maui.Sample/App.xaml
@@ -1,5 +1,6 @@
@@ -7,6 +8,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/CommunityToolkit.Maui.Sample/AppShell.xaml.cs b/samples/CommunityToolkit.Maui.Sample/AppShell.xaml.cs
index 22db9606f..3409c2bd4 100644
--- a/samples/CommunityToolkit.Maui.Sample/AppShell.xaml.cs
+++ b/samples/CommunityToolkit.Maui.Sample/AppShell.xaml.cs
@@ -129,6 +129,7 @@ public partial class AppShell : Shell
CreateViewModelMapping(),
CreateViewModelMapping(),
CreateViewModelMapping(),
+ CreateViewModelMapping(),
});
public AppShell() => InitializeComponent();
diff --git a/samples/CommunityToolkit.Maui.Sample/CommunityToolkit.Maui.Sample.csproj b/samples/CommunityToolkit.Maui.Sample/CommunityToolkit.Maui.Sample.csproj
index 9c2b7812a..d95a157be 100644
--- a/samples/CommunityToolkit.Maui.Sample/CommunityToolkit.Maui.Sample.csproj
+++ b/samples/CommunityToolkit.Maui.Sample/CommunityToolkit.Maui.Sample.csproj
@@ -1,4 +1,4 @@
-
+
$(NetVersion)-ios;$(NetVersion)-android;$(NetVersion)-maccatalyst
diff --git a/samples/CommunityToolkit.Maui.Sample/MauiProgram.cs b/samples/CommunityToolkit.Maui.Sample/MauiProgram.cs
index 6a01ed0fe..3cfe62c43 100644
--- a/samples/CommunityToolkit.Maui.Sample/MauiProgram.cs
+++ b/samples/CommunityToolkit.Maui.Sample/MauiProgram.cs
@@ -192,6 +192,7 @@ static void RegisterViewsAndViewModels(in IServiceCollection services)
services.AddTransientWithShellRoute();
services.AddTransientWithShellRoute();
services.AddTransientWithShellRoute();
+ services.AddTransientWithShellRoute();
// Add Popups
services.AddTransient();
diff --git a/samples/CommunityToolkit.Maui.Sample/Pages/Views/Popup/StylePopupPage.xaml b/samples/CommunityToolkit.Maui.Sample/Pages/Views/Popup/StylePopupPage.xaml
new file mode 100644
index 000000000..f1fa1719d
--- /dev/null
+++ b/samples/CommunityToolkit.Maui.Sample/Pages/Views/Popup/StylePopupPage.xaml
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/CommunityToolkit.Maui.Sample/Pages/Views/Popup/StylePopupPage.xaml.cs b/samples/CommunityToolkit.Maui.Sample/Pages/Views/Popup/StylePopupPage.xaml.cs
new file mode 100644
index 000000000..46ab0c8c3
--- /dev/null
+++ b/samples/CommunityToolkit.Maui.Sample/Pages/Views/Popup/StylePopupPage.xaml.cs
@@ -0,0 +1,10 @@
+using CommunityToolkit.Maui.Sample.ViewModels.Views;
+namespace CommunityToolkit.Maui.Sample.Pages.Views;
+
+public partial class StylePopupPage : BasePage
+{
+ public StylePopupPage(StylePopupViewModel stylePopupViewModel) : base(stylePopupViewModel)
+ {
+ InitializeComponent();
+ }
+}
\ No newline at end of file
diff --git a/samples/CommunityToolkit.Maui.Sample/ViewModels/Views/Popup/StylePopupViewModel.cs b/samples/CommunityToolkit.Maui.Sample/ViewModels/Views/Popup/StylePopupViewModel.cs
new file mode 100644
index 000000000..592b5cdc6
--- /dev/null
+++ b/samples/CommunityToolkit.Maui.Sample/ViewModels/Views/Popup/StylePopupViewModel.cs
@@ -0,0 +1,59 @@
+using CommunityToolkit.Maui.Sample.Views.Popups;
+using CommunityToolkit.Maui.Views;
+using CommunityToolkit.Mvvm.Input;
+
+namespace CommunityToolkit.Maui.Sample.ViewModels.Views;
+
+public partial class StylePopupViewModel : BaseViewModel
+{
+ static Page MainPage => Shell.Current;
+
+ [RelayCommand]
+ static void DisplayImplicitStylePopup()
+ {
+ var popup = new ImplicitStylePopup();
+ MainPage.ShowPopup(popup);
+ }
+
+ [RelayCommand]
+ static void DisplayExplicitStylePopup()
+ {
+ var popup = new ExplicitStylePopup();
+ MainPage.ShowPopup(popup);
+ }
+
+ [RelayCommand]
+ static void DisplayDynamicStylePopup()
+ {
+ var popup = new DynamicStylePopup();
+ MainPage.ShowPopup(popup);
+ }
+
+ [RelayCommand]
+ static void DisplayApplyToDerivedTypesPopup()
+ {
+ var popup = new ApplyToDerivedTypesPopup();
+ MainPage.ShowPopup(popup);
+ }
+
+ [RelayCommand]
+ static void DisplayStyleInheritancePopup()
+ {
+ var popup = new StyleInheritancePopup();
+ MainPage.ShowPopup(popup);
+ }
+
+ [RelayCommand]
+ static void DisplayDynamicStyleInheritancePopup()
+ {
+ var popup = new DynamicStyleInheritancePopup();
+ MainPage.ShowPopup(popup);
+ }
+
+ [RelayCommand]
+ static void DisplayStyleClassPopup()
+ {
+ var popup = new StyleClassPopup();
+ MainPage.ShowPopup(popup);
+ }
+}
\ No newline at end of file
diff --git a/samples/CommunityToolkit.Maui.Sample/ViewModels/Views/ViewsGalleryViewModel.cs b/samples/CommunityToolkit.Maui.Sample/ViewModels/Views/ViewsGalleryViewModel.cs
index 3dd143937..0289cbe8a 100644
--- a/samples/CommunityToolkit.Maui.Sample/ViewModels/Views/ViewsGalleryViewModel.cs
+++ b/samples/CommunityToolkit.Maui.Sample/ViewModels/Views/ViewsGalleryViewModel.cs
@@ -32,6 +32,7 @@ public ViewsGalleryViewModel()
SectionModel.Create("Popup Layout Page", Colors.Red, "Popup.Content demonstrated using different layouts"),
SectionModel.Create("Show Popup in OnAppearing", Colors.Red, "Proves that we now support showing a popup before the platform is even ready."),
SectionModel.Create("Semantic Order View", Colors.Red, "SemanticOrderView allows developers to indicate the focus order of visible controls when a user is navigating via TalkBack (Android), VoiceOver (iOS) or Narrator (Windows)."),
+ SectionModel.Create("Popup Style Page", Colors.Red, "A page demonstrating how Popups can be styled in a .NET MAUI application."),
})
{
}
diff --git a/samples/CommunityToolkit.Maui.Sample/Views/Popups/ApplyToDerivedTypesPopup.xaml b/samples/CommunityToolkit.Maui.Sample/Views/Popups/ApplyToDerivedTypesPopup.xaml
new file mode 100644
index 000000000..0df8c9625
--- /dev/null
+++ b/samples/CommunityToolkit.Maui.Sample/Views/Popups/ApplyToDerivedTypesPopup.xaml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/CommunityToolkit.Maui.Sample/Views/Popups/ApplyToDerivedTypesPopup.xaml.cs b/samples/CommunityToolkit.Maui.Sample/Views/Popups/ApplyToDerivedTypesPopup.xaml.cs
new file mode 100644
index 000000000..f8093fc0e
--- /dev/null
+++ b/samples/CommunityToolkit.Maui.Sample/Views/Popups/ApplyToDerivedTypesPopup.xaml.cs
@@ -0,0 +1,15 @@
+using CommunityToolkit.Maui.Views;
+
+namespace CommunityToolkit.Maui.Sample.Views.Popups;
+
+///
+/// This popup demonstrates how the ApplyToDerivedTypes property can allow for Popup implementations
+/// that inherit from Popup to still use a common Style definition.
+///
+public partial class ApplyToDerivedTypesPopup : Popup
+{
+ public ApplyToDerivedTypesPopup()
+ {
+ InitializeComponent();
+ }
+}
\ No newline at end of file
diff --git a/samples/CommunityToolkit.Maui.Sample/Views/Popups/DynamicStyleInheritancePopup.xaml b/samples/CommunityToolkit.Maui.Sample/Views/Popups/DynamicStyleInheritancePopup.xaml
new file mode 100644
index 000000000..c66dc90a7
--- /dev/null
+++ b/samples/CommunityToolkit.Maui.Sample/Views/Popups/DynamicStyleInheritancePopup.xaml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/CommunityToolkit.Maui.Sample/Views/Popups/DynamicStyleInheritancePopup.xaml.cs b/samples/CommunityToolkit.Maui.Sample/Views/Popups/DynamicStyleInheritancePopup.xaml.cs
new file mode 100644
index 000000000..f5ce631f5
--- /dev/null
+++ b/samples/CommunityToolkit.Maui.Sample/Views/Popups/DynamicStyleInheritancePopup.xaml.cs
@@ -0,0 +1,11 @@
+using CommunityToolkit.Maui.Views;
+
+namespace CommunityToolkit.Maui.Sample.Views.Popups;
+
+public partial class DynamicStyleInheritancePopup : Popup
+{
+ public DynamicStyleInheritancePopup()
+ {
+ InitializeComponent();
+ }
+}
\ No newline at end of file
diff --git a/samples/CommunityToolkit.Maui.Sample/Views/Popups/DynamicStylePopup.xaml b/samples/CommunityToolkit.Maui.Sample/Views/Popups/DynamicStylePopup.xaml
new file mode 100644
index 000000000..a139719c6
--- /dev/null
+++ b/samples/CommunityToolkit.Maui.Sample/Views/Popups/DynamicStylePopup.xaml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/CommunityToolkit.Maui.Sample/Views/Popups/DynamicStylePopup.xaml.cs b/samples/CommunityToolkit.Maui.Sample/Views/Popups/DynamicStylePopup.xaml.cs
new file mode 100644
index 000000000..d8b014820
--- /dev/null
+++ b/samples/CommunityToolkit.Maui.Sample/Views/Popups/DynamicStylePopup.xaml.cs
@@ -0,0 +1,15 @@
+using CommunityToolkit.Maui.Views;
+
+namespace CommunityToolkit.Maui.Sample.Views.Popups;
+
+///
+/// This popup demonstrates how a is applied to a
+/// through the use of the property using the .
+///
+public partial class DynamicStylePopup : Popup
+{
+ public DynamicStylePopup()
+ {
+ InitializeComponent();
+ }
+}
\ No newline at end of file
diff --git a/samples/CommunityToolkit.Maui.Sample/Views/Popups/ExplicitStylePopup.xaml b/samples/CommunityToolkit.Maui.Sample/Views/Popups/ExplicitStylePopup.xaml
new file mode 100644
index 000000000..9c9459646
--- /dev/null
+++ b/samples/CommunityToolkit.Maui.Sample/Views/Popups/ExplicitStylePopup.xaml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/CommunityToolkit.Maui.Sample/Views/Popups/ExplicitStylePopup.xaml.cs b/samples/CommunityToolkit.Maui.Sample/Views/Popups/ExplicitStylePopup.xaml.cs
new file mode 100644
index 000000000..91e96df9a
--- /dev/null
+++ b/samples/CommunityToolkit.Maui.Sample/Views/Popups/ExplicitStylePopup.xaml.cs
@@ -0,0 +1,15 @@
+using CommunityToolkit.Maui.Views;
+
+namespace CommunityToolkit.Maui.Sample.Views.Popups;
+
+///
+/// This popup demonstrates how a is applied to a explicitly
+/// through the use of the property using the .
+///
+public partial class ExplicitStylePopup : Popup
+{
+ public ExplicitStylePopup()
+ {
+ InitializeComponent();
+ }
+}
\ No newline at end of file
diff --git a/samples/CommunityToolkit.Maui.Sample/Views/Popups/ImplicitStylePopup.xaml b/samples/CommunityToolkit.Maui.Sample/Views/Popups/ImplicitStylePopup.xaml
new file mode 100644
index 000000000..29e50ae6c
--- /dev/null
+++ b/samples/CommunityToolkit.Maui.Sample/Views/Popups/ImplicitStylePopup.xaml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/CommunityToolkit.Maui.Sample/Views/Popups/ImplicitStylePopup.xaml.cs b/samples/CommunityToolkit.Maui.Sample/Views/Popups/ImplicitStylePopup.xaml.cs
new file mode 100644
index 000000000..2c785b2b5
--- /dev/null
+++ b/samples/CommunityToolkit.Maui.Sample/Views/Popups/ImplicitStylePopup.xaml.cs
@@ -0,0 +1,15 @@
+using CommunityToolkit.Maui.Views;
+
+namespace CommunityToolkit.Maui.Sample.Views.Popups;
+
+///
+/// This popup demonstrates how a is applied to a implictly
+/// through the use of only the property.
+///
+public partial class ImplicitStylePopup : Popup
+{
+ public ImplicitStylePopup()
+ {
+ InitializeComponent();
+ }
+}
\ No newline at end of file
diff --git a/samples/CommunityToolkit.Maui.Sample/Views/Popups/StyleClassPopup.xaml b/samples/CommunityToolkit.Maui.Sample/Views/Popups/StyleClassPopup.xaml
new file mode 100644
index 000000000..080cdd308
--- /dev/null
+++ b/samples/CommunityToolkit.Maui.Sample/Views/Popups/StyleClassPopup.xaml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/CommunityToolkit.Maui.Sample/Views/Popups/StyleClassPopup.xaml.cs b/samples/CommunityToolkit.Maui.Sample/Views/Popups/StyleClassPopup.xaml.cs
new file mode 100644
index 000000000..db92e5b37
--- /dev/null
+++ b/samples/CommunityToolkit.Maui.Sample/Views/Popups/StyleClassPopup.xaml.cs
@@ -0,0 +1,15 @@
+using CommunityToolkit.Maui.Views;
+
+namespace CommunityToolkit.Maui.Sample.Views.Popups;
+
+///
+/// This popup demonstrates how the property can be used to apply
+/// a definition to a .
+///
+public partial class StyleClassPopup : Popup
+{
+ public StyleClassPopup()
+ {
+ InitializeComponent();
+ }
+}
\ No newline at end of file
diff --git a/samples/CommunityToolkit.Maui.Sample/Views/Popups/StyleInheritancePopup.xaml b/samples/CommunityToolkit.Maui.Sample/Views/Popups/StyleInheritancePopup.xaml
new file mode 100644
index 000000000..f05c87fe9
--- /dev/null
+++ b/samples/CommunityToolkit.Maui.Sample/Views/Popups/StyleInheritancePopup.xaml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/CommunityToolkit.Maui.Sample/Views/Popups/StyleInheritancePopup.xaml.cs b/samples/CommunityToolkit.Maui.Sample/Views/Popups/StyleInheritancePopup.xaml.cs
new file mode 100644
index 000000000..3d3edc21c
--- /dev/null
+++ b/samples/CommunityToolkit.Maui.Sample/Views/Popups/StyleInheritancePopup.xaml.cs
@@ -0,0 +1,15 @@
+using CommunityToolkit.Maui.Views;
+
+namespace CommunityToolkit.Maui.Sample.Views.Popups;
+
+///
+/// This popup demonstrates how the property can allow for Popup implementations
+/// that inherit from to still use a common definition.
+///
+public partial class StyleInheritancePopup : Popup
+{
+ public StyleInheritancePopup()
+ {
+ InitializeComponent();
+ }
+}
\ No newline at end of file
diff --git a/src/CommunityToolkit.Maui/Views/Popup/Popup.shared.cs b/src/CommunityToolkit.Maui/Views/Popup/Popup.shared.cs
index eef0f7267..b7d1b3f85 100644
--- a/src/CommunityToolkit.Maui/Views/Popup/Popup.shared.cs
+++ b/src/CommunityToolkit.Maui/Views/Popup/Popup.shared.cs
@@ -1,6 +1,8 @@
using CommunityToolkit.Maui.Core;
using Microsoft.Maui.Controls.Internals;
+using Microsoft.Maui.Controls.StyleSheets;
using LayoutAlignment = Microsoft.Maui.Primitives.LayoutAlignment;
+using Style = Microsoft.Maui.Controls.Style;
namespace CommunityToolkit.Maui.Views;
@@ -8,7 +10,7 @@ namespace CommunityToolkit.Maui.Views;
/// Represents a small View that pops up at front the Page. Implements .
///
[ContentProperty(nameof(Content))]
-public partial class Popup : Element, IPopup, IWindowController, IPropertyPropagationController
+public partial class Popup : Element, IPopup, IWindowController, IPropertyPropagationController, IResourcesProvider, IStyleSelectable, IStyleElement
{
///
/// Backing BindableProperty for the property.
@@ -40,13 +42,21 @@ public partial class Popup : Element, IPopup, IWindowController, IPropertyPropag
///
public static readonly BindableProperty HorizontalOptionsProperty = BindableProperty.Create(nameof(HorizontalOptions), typeof(LayoutAlignment), typeof(Popup), LayoutAlignment.Center);
+ ///
+ /// Backing BindableProperty for the property.
+ ///
+ public static readonly BindableProperty StyleProperty = BindableProperty.Create(nameof(Style), typeof(Style), typeof(Popup), default(Style), propertyChanged: (bindable, oldValue, newValue) => ((Popup)bindable).mergedStyle.Style = (Style)newValue);
+
readonly WeakEventManager dismissWeakEventManager = new();
readonly WeakEventManager openedWeakEventManager = new();
readonly Lazy> platformConfigurationRegistry;
+ readonly MergedStyle mergedStyle;
TaskCompletionSource popupDismissedTaskCompletionSource = new();
TaskCompletionSource