Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "Expose AutomationOption Setter for ChildSite",
"packageName": "react-native-windows",
"email": "66076509+vineethkuttan@users.noreply.github.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
Expand Up @@ -212,13 +212,17 @@ void ContentIslandComponentView::prepareForRecycle() noexcept {
}

void ContentIslandComponentView::ConfigureChildSiteLinkAutomation() noexcept {
// Use FrameworkBased to let the XamlIsland manage its own framework-level accessibility tree
// and raise focus events naturally. This tells the system that the child island has its own
// framework (WinUI/XAML) that manages automation.
m_childSiteLink.AutomationOption(winrt::Microsoft::UI::Content::ContentAutomationOptions::FrameworkBased);
// Determine the automation option to use:
// 1. If explicitly set via builder, use that
// 2. Otherwise, default to FrameworkBased
winrt::Microsoft::UI::Content::ContentAutomationOptions automationOption =
winrt::Microsoft::UI::Content::ContentAutomationOptions::FrameworkBased;
if (m_builder && m_builder->ContentIslandChildSiteAutomationOption().has_value()) {
automationOption = m_builder->ContentIslandChildSiteAutomationOption().value();
}
Comment on lines +220 to +222
Copy link
Contributor

@sundaramramaswamy sundaramramaswamy Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (m_builder && m_builder->ContentIslandChildSiteAutomationOption().has_value()) {
automationOption = m_builder->ContentIslandChildSiteAutomationOption().value();
}
if (m_builder->ContentIslandChildSiteAutomationOption()) {
automationOption = *m_builder->ContentIslandChildSiteAutomationOption();
}
  1. Can m_builder ever be nullptr within the lifetime of this object? If yes, then won't every usage of this member variable be starting with a if (m_builder) check? That would be unperformant, ugly and noisy, yes?

  2. std::optional::operator bool automatically does what has_value() does. Excerpt from std::optional:

When an object of type optional is contextually converted to bool, the conversion returns true if the object contains a value and false if it does not contain a value.

  1. operator* returns the value within.

Even better is to use std::optional::or_value which gives the value if there's a value else defaults to whatever you pass it.

  const winrt::Microsoft::UI::Content::ContentAutomationOptions automationOption = m_builder->ContentIslandChildSiteAutomationOption().value_or(winrt::Microsoft::UI::Content::ContentAutomationOptions::FrameworkBased);

Shorter, cleaner and clearer to read, no? As a bonus since you initialize the variable in one statement, it can be qualified const now.

Moral: It helps to read the documentation and many things are perhaps already done for you. You just have to use them, for that you've to know them.


m_childSiteLink.AutomationOption(automationOption);

// When using FrameworkBased mode, we don't register automation callbacks - let the XamlIsland handle its own UIA
// tree.
if (m_innerAutomationProvider) {
m_innerAutomationProvider->SetChildSiteLink(m_childSiteLink);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,16 @@ void ReactCompositionViewComponentBuilder::SetContentIslandComponentViewInitiali
};
}

void ReactCompositionViewComponentBuilder::SetContentIslandChildSiteAutomationOption(
winrt::Microsoft::UI::Content::ContentAutomationOptions automationOption) noexcept {
m_contentIslandChildSiteAutomationOption = automationOption;
}

std::optional<winrt::Microsoft::UI::Content::ContentAutomationOptions>
ReactCompositionViewComponentBuilder::ContentIslandChildSiteAutomationOption() const noexcept {
return m_contentIslandChildSiteAutomationOption;
}

void ReactCompositionViewComponentBuilder::SetPortalComponentViewInitializer(
const PortalComponentViewInitializer &initializer) noexcept {
m_fnCreateView = [initializer](
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <Fabric/AbiComponentDescriptor.h>
#include <react/renderer/componentregistry/ComponentDescriptorProvider.h>
#include <react/renderer/core/ReactPrimitives.h>
#include <optional>
#include "winrt/Microsoft.ReactNative.Composition.Experimental.h"
#include "winrt/Microsoft.ReactNative.Composition.h"
#include "winrt/Microsoft.ReactNative.h"
Expand Down Expand Up @@ -46,6 +47,8 @@ struct ReactCompositionViewComponentBuilder
public: // Composition::IReactCompositionViewComponentBuilder
void SetViewComponentViewInitializer(const ViewComponentViewInitializer &initializer) noexcept;
void SetContentIslandComponentViewInitializer(const ComponentIslandComponentViewInitializer &initializer) noexcept;
void SetContentIslandChildSiteAutomationOption(
winrt::Microsoft::UI::Content::ContentAutomationOptions automationOption) noexcept;
void SetPortalComponentViewInitializer(const PortalComponentViewInitializer &initializer) noexcept;
void SetCreateVisualHandler(CreateVisualDelegate impl) noexcept;
void SetViewFeatures(ComponentViewFeatures viewFeatures) noexcept;
Expand Down Expand Up @@ -81,6 +84,8 @@ struct ReactCompositionViewComponentBuilder
const winrt::Microsoft::ReactNative::Composition::Experimental::IVisualToMountChildrenIntoDelegate &
VisualToMountChildrenIntoHandler() const noexcept;
const CreateAutomationPeerDelegate &CreateAutomationPeerHandler() const noexcept;
std::optional<winrt::Microsoft::UI::Content::ContentAutomationOptions> ContentIslandChildSiteAutomationOption()
const noexcept;

private:
void InitializeComponentView(const winrt::Microsoft::ReactNative::ComponentView &view) noexcept;
Expand Down Expand Up @@ -114,6 +119,7 @@ struct ReactCompositionViewComponentBuilder
m_visualToMountChildrenIntoHandler;
UpdateLayoutMetricsDelegate m_updateLayoutMetricsHandler;
bool m_xamlSupport{false};
std::optional<winrt::Microsoft::UI::Content::ContentAutomationOptions> m_contentIslandChildSiteAutomationOption;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this an optional? Is it because ContentAutomationOptions::None can be set by the 3P module and we want to differentiate that case from not being set all?

Copy link
Contributor Author

@vineethkuttan vineethkuttan Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes Sundaram. Since it is enum class , it will have default value which is None. So added optional to differentiate that case from not being set at all.

Or I may need to set the default value as frameworkbased in the contructor.

};

} // namespace winrt::Microsoft::ReactNative::Composition
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ namespace Microsoft.ReactNative.Composition
[experimental]
delegate void ComponentIslandComponentViewInitializer(ContentIslandComponentView view);


[webhosthidden]
[experimental]
delegate void PortalComponentViewInitializer(PortalComponentView view);
Expand Down Expand Up @@ -68,6 +69,7 @@ namespace Microsoft.ReactNative.Composition
{
void SetViewComponentViewInitializer(ViewComponentViewInitializer initializer);
void SetContentIslandComponentViewInitializer(ComponentIslandComponentViewInitializer initializer);
void SetContentIslandChildSiteAutomationOption(Microsoft.UI.Content.ContentAutomationOptions automationOption);
void SetPortalComponentViewInitializer(PortalComponentViewInitializer initializer);
void SetCreateVisualHandler(CreateVisualDelegate impl);
void SetViewFeatures(ComponentViewFeatures viewFeatures);
Expand Down
Loading