diff --git a/change/react-native-windows-77e0d25a-8269-4693-8568-96ba49675a87.json b/change/react-native-windows-77e0d25a-8269-4693-8568-96ba49675a87.json new file mode 100644 index 00000000000..27812246d03 --- /dev/null +++ b/change/react-native-windows-77e0d25a-8269-4693-8568-96ba49675a87.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "Switch to MUX:CommandBarFlyout in XAML Islands proofing menu", + "packageName": "react-native-windows", + "email": "jthysell@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.cpp b/vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.cpp index d5f93ed12c1..091cabc88f7 100644 --- a/vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.cpp +++ b/vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.cpp @@ -30,14 +30,23 @@ struct CustomAppBarButton : xaml::Controls::AppBarButtonT { } }; -void FixProofingMenuCrashForXamlIsland(xaml::Controls::TextCommandBarFlyout const &flyout) { +void FixProofingMenuCrashForXamlIsland(xaml::Controls::Primitives::FlyoutBase const &flyout) { flyout.Opening([](winrt::IInspectable const &sender, auto &&) { - const auto &flyout = sender.as(); + const auto &flyout = sender.as(); if (const auto &textBox = flyout.Target().try_as()) { const auto &commands = flyout.SecondaryCommands(); for (uint32_t i = 0; i < commands.Size(); ++i) { if (const auto &appBarButton = commands.GetAt(i).try_as()) { - if (appBarButton.Flyout() == textBox.ProofingMenuFlyout()) { + if (!appBarButton.Flyout()) { + // This works around a loss of focus from the target element when clicking on + // on the menu items. + // https://github.com/microsoft/microsoft-ui-xaml/issues/5818 + appBarButton.Click([weakCommandBarFlyout = winrt::make_weak(flyout)](auto &&...) { + if (auto flyout = weakCommandBarFlyout.get()) { + xaml::Input::FocusManager::TryFocusAsync(flyout.Target(), xaml::FocusState::Programmatic); + } + }); + } else if (appBarButton.Flyout() == textBox.ProofingMenuFlyout()) { if (!appBarButton.try_as()) { // Replace the AppBarButton for the proofing menu with one that doesn't crash const auto customAppBarButton = winrt::make(); diff --git a/vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.h b/vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.h index d00d4f1ed95..87c8c728df8 100644 --- a/vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.h +++ b/vnext/Microsoft.ReactNative/Utils/XamlIslandUtils.h @@ -8,9 +8,11 @@ #include #include +#include + namespace Microsoft::ReactNative { -void FixProofingMenuCrashForXamlIsland(xaml::Controls::TextCommandBarFlyout const &flyout); +void FixProofingMenuCrashForXamlIsland(xaml::Controls::Primitives::FlyoutBase const &flyout); template inline void EnsureUniqueTextFlyoutForXamlIsland(T const &textView) { @@ -19,7 +21,7 @@ inline void EnsureUniqueTextFlyoutForXamlIsland(T const &textView) { // to show the flyout on other windows cause the first window to get focus. // https://github.com/microsoft/microsoft-ui-xaml/issues/5341 if (IsXamlIsland()) { - xaml::Controls::TextCommandBarFlyout flyout; + winrt::Microsoft::UI::Xaml::Controls::TextCommandBarFlyout flyout; flyout.Placement(xaml::Controls::Primitives::FlyoutPlacementMode::BottomEdgeAlignedLeft); // This works around a XAML Islands bug where the Proofing sub-menu for