Fix XAML popup positioning and light dismiss in ScrollView (#15557) #15564
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Description
This PR fixes Issue #15557 - "Pop-ups of Xaml controls need positioning and dismissal"
When XAML controls with popups (like ComboBox, DatePicker, TimePicker) are hosted inside a React Native ScrollView via
ContentIslandComponentView, two bugs occur:Root Cause
ContentIslandComponentViewusesChildSiteLink.LocalToParentTransformMatrixfor popup positioning, but wasn't being notified when scroll position changedSolution
Bug 1 Fix: Popup Position After Scroll
ScrollViewComponentViewnow firesLayoutMetricsChangedevent when scroll position changesContentIslandComponentViewlistens to this and callsParentLayoutChanged()LocalToParentTransformMatrixwith the correct scroll offset viagetClientRect()Bug 2 Fix: Light Dismiss on Scroll (Generic for ALL 3rd Party XAML Controls)
SetXamlRoot(XamlRoot)method toContentIslandComponentViewAPIXamlRootafter the element is loadedDismissPopups()usesVisualTreeHelper.GetOpenPopupsForXamlRoot()to find and close ALL open XAML popupsFiles Changed
Core Fix (vnext/Microsoft.ReactNative/)
CompositionComponentView.idl- AddedSetXamlRoot()method toContentIslandComponentViewFabric/Composition/ContentIslandComponentView.h/.cpp- ImplementedSetXamlRoot()andDismissPopups()Fabric/Composition/ScrollViewComponentView.h/.cpp- Added scroll position change notification and popup dismissal triggerSample Component (packages/sample-custom-component/)
ComboBoxcomponent as example of proper 3rd party implementationSetXamlRoot()for popup dismissalTest Samples
XamlPopupRepro.windows.tsx- Test case in RNTesterxamlPopupBug.tsx- Test case in Playground🔧 Guidance for 3rd Party XAML Component Developers
If you're building a custom XAML component that has popups (ComboBox, DatePicker, Flyouts, etc.), follow this pattern to ensure proper popup behavior inside React Native ScrollViews:
C++ Implementation Pattern
Why This Works
Position Fix: The framework automatically updates
LocalToParentTransformMatrixwhen scroll position changes, so your popup appears at the correct location.Light Dismiss: When you register your
XamlRoot, the framework usesVisualTreeHelper.GetOpenPopupsForXamlRoot()to find ALL open popups when scroll begins and closes them automatically.What else handled with this fix
Testing
XamlPopupReprosample in PlaygroundMicrosoft Reviewers: Open in CodeFlow