From d8242a41e37f24070f6b6f4b3a4405b081fdc37f Mon Sep 17 00:00:00 2001
From: Abhijeet Jha <74712637+iamAbhi-916@users.noreply.github.com>
Date: Mon, 19 Jan 2026 10:18:23 +0530
Subject: [PATCH] Implements selectionColor for (#15553)
* implements selectionColor
* Change files
---
...-28d68603-5db6-40f6-9d44-4a5b489813d4.json | 7 +
packages/playground/Samples/text.tsx | 41 ++++-
.../Composition/ParagraphComponentView.cpp | 13 +-
.../components/text/BaseParagraphProps.cpp | 174 ++++++++++++++++++
.../components/text/BaseParagraphProps.h | 69 +++++++
vnext/overrides.json | 14 ++
6 files changed, 315 insertions(+), 3 deletions(-)
create mode 100644 change/react-native-windows-28d68603-5db6-40f6-9d44-4a5b489813d4.json
create mode 100644 vnext/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/text/BaseParagraphProps.cpp
create mode 100644 vnext/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/text/BaseParagraphProps.h
diff --git a/change/react-native-windows-28d68603-5db6-40f6-9d44-4a5b489813d4.json b/change/react-native-windows-28d68603-5db6-40f6-9d44-4a5b489813d4.json
new file mode 100644
index 00000000000..e9f5b2f70ae
--- /dev/null
+++ b/change/react-native-windows-28d68603-5db6-40f6-9d44-4a5b489813d4.json
@@ -0,0 +1,7 @@
+{
+ "type": "prerelease",
+ "comment": "implements selectionColor",
+ "packageName": "react-native-windows",
+ "email": "74712637+iamAbhi-916@users.noreply.github.com",
+ "dependentChangeType": "patch"
+}
diff --git a/packages/playground/Samples/text.tsx b/packages/playground/Samples/text.tsx
index e5ce13a5090..a3143746077 100644
--- a/packages/playground/Samples/text.tsx
+++ b/packages/playground/Samples/text.tsx
@@ -37,10 +37,42 @@ export default class Bootstrap extends React.Component {
+
+ Selection Color Test
+
+ Red selection color - Select this text to see red highlight!
+
+
+ Green selection color (#00FF00) - Select this text!
+
+
+ Orange with 50% opacity - Select this text!
+
+
+ Blue selection color - Select this text!
+
+
+ Default selection color (no selectionColor prop) - Uses theme
+ default.
+
+
+
selectionBrush;
- const D2D1_COLOR_F selectionColor = theme()->D2DPlatformColor("Highlight@40");
+ D2D1_COLOR_F selectionColor;
+ const auto &props = paragraphProps();
+ if (props.selectionColor) {
+ selectionColor = theme()->D2DColor(**props.selectionColor);
+ } else {
+ selectionColor = theme()->D2DPlatformColor("Highlight@40");
+ }
hr = renderTarget.CreateSolidColorBrush(selectionColor, selectionBrush.put());
if (FAILED(hr)) {
diff --git a/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/text/BaseParagraphProps.cpp b/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/text/BaseParagraphProps.cpp
new file mode 100644
index 00000000000..e2f3091a321
--- /dev/null
+++ b/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/text/BaseParagraphProps.cpp
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+#include "BaseParagraphProps.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+namespace facebook::react {
+
+BaseParagraphProps::BaseParagraphProps(
+ const PropsParserContext& context,
+ const BaseParagraphProps& sourceProps,
+ const RawProps& rawProps)
+ : ViewProps(context, sourceProps, rawProps),
+ BaseTextProps(context, sourceProps, rawProps),
+ paragraphAttributes(
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
+ ? sourceProps.paragraphAttributes
+ : convertRawProp(
+ context,
+ rawProps,
+ sourceProps.paragraphAttributes,
+ {})),
+ isSelectable(
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
+ ? sourceProps.isSelectable
+ : convertRawProp(
+ context,
+ rawProps,
+ "selectable",
+ sourceProps.isSelectable,
+ false)),
+ onTextLayout(
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
+ ? sourceProps.onTextLayout
+ : convertRawProp(
+ context,
+ rawProps,
+ "onTextLayout",
+ sourceProps.onTextLayout,
+ {})),
+ // [Windows]
+ selectionColor(
+ ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
+ ? sourceProps.selectionColor
+ : convertRawProp(
+ context,
+ rawProps,
+ "selectionColor",
+ sourceProps.selectionColor,
+ {})) {
+ /*
+ * These props are applied to `View`, therefore they must not be a part of
+ * base text attributes.
+ */
+ textAttributes.opacity = std::numeric_limits::quiet_NaN();
+ textAttributes.backgroundColor = {};
+};
+
+void BaseParagraphProps::setProp(
+ const PropsParserContext& context,
+ RawPropsPropNameHash hash,
+ const char* propName,
+ const RawValue& value) {
+ // All Props structs setProp methods must always, unconditionally,
+ // call all super::setProp methods, since multiple structs may
+ // reuse the same values.
+ ViewProps::setProp(context, hash, propName, value);
+ BaseTextProps::setProp(context, hash, propName, value);
+
+ static auto defaults = BaseParagraphProps{};
+
+ // ParagraphAttributes has its own switch statement - to keep all
+ // of these fields together, and because there are some collisions between
+ // propnames parsed here and outside of ParagraphAttributes.
+ // This code is also duplicated in AndroidTextInput.
+ static auto paDefaults = ParagraphAttributes{};
+ switch (hash) {
+ REBUILD_FIELD_SWITCH_CASE(
+ paDefaults,
+ value,
+ paragraphAttributes,
+ maximumNumberOfLines,
+ "numberOfLines");
+ REBUILD_FIELD_SWITCH_CASE(
+ paDefaults, value, paragraphAttributes, ellipsizeMode, "ellipsizeMode");
+ REBUILD_FIELD_SWITCH_CASE(
+ paDefaults,
+ value,
+ paragraphAttributes,
+ textBreakStrategy,
+ "textBreakStrategy");
+ REBUILD_FIELD_SWITCH_CASE(
+ paDefaults,
+ value,
+ paragraphAttributes,
+ adjustsFontSizeToFit,
+ "adjustsFontSizeToFit");
+ REBUILD_FIELD_SWITCH_CASE(
+ paDefaults,
+ value,
+ paragraphAttributes,
+ minimumFontScale,
+ "minimumFontScale");
+ REBUILD_FIELD_SWITCH_CASE(
+ paDefaults,
+ value,
+ paragraphAttributes,
+ minimumFontSize,
+ "minimumFontSize");
+ REBUILD_FIELD_SWITCH_CASE(
+ paDefaults,
+ value,
+ paragraphAttributes,
+ maximumFontSize,
+ "maximumFontSize");
+ REBUILD_FIELD_SWITCH_CASE(
+ paDefaults,
+ value,
+ paragraphAttributes,
+ includeFontPadding,
+ "includeFontPadding");
+ REBUILD_FIELD_SWITCH_CASE(
+ paDefaults,
+ value,
+ paragraphAttributes,
+ android_hyphenationFrequency,
+ "android_hyphenationFrequency");
+ REBUILD_FIELD_SWITCH_CASE(
+ paDefaults,
+ value,
+ paragraphAttributes,
+ textAlignVertical,
+ "textAlignVertical");
+ }
+
+ switch (hash) {
+ RAW_SET_PROP_SWITCH_CASE(isSelectable, "selectable");
+ RAW_SET_PROP_SWITCH_CASE_BASIC(onTextLayout);
+ // [Windows]
+ RAW_SET_PROP_SWITCH_CASE_BASIC(selectionColor);
+ }
+
+ /*
+ * These props are applied to `View`, therefore they must not be a part of
+ * base text attributes.
+ */
+ textAttributes.opacity = std::numeric_limits::quiet_NaN();
+ textAttributes.backgroundColor = {};
+}
+
+#pragma mark - DebugStringConvertible
+
+#if RN_DEBUG_STRING_CONVERTIBLE
+SharedDebugStringConvertibleList BaseParagraphProps::getDebugProps() const {
+ return ViewProps::getDebugProps() + BaseTextProps::getDebugProps() +
+ paragraphAttributes.getDebugProps() +
+ SharedDebugStringConvertibleList{
+ debugStringConvertibleItem("selectable", isSelectable),
+ // [Windows]
+ debugStringConvertibleItem("selectionColor", selectionColor)};
+}
+#endif
+} // namespace facebook::react
diff --git a/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/text/BaseParagraphProps.h b/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/text/BaseParagraphProps.h
new file mode 100644
index 00000000000..b2ac7275c17
--- /dev/null
+++ b/vnext/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/text/BaseParagraphProps.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+#pragma once
+
+#include
+#include
+// [Windows]
+#include
+
+#include
+#include
+#include
+#include
+#include
+// [Windows]
+#include
+
+namespace facebook::react {
+
+/*
+ * Props of component.
+ * Most of the props are directly stored in composed `ParagraphAttributes`
+ * object.
+ */
+class BaseParagraphProps : public ViewProps, public BaseTextProps {
+ public:
+ BaseParagraphProps() = default;
+ BaseParagraphProps(
+ const PropsParserContext &context,
+ const BaseParagraphProps &sourceProps,
+ const RawProps &rawProps);
+
+ void
+ setProp(const PropsParserContext &context, RawPropsPropNameHash hash, const char *propName, const RawValue &value);
+
+#pragma mark - Props
+
+ /*
+ * Contains all prop values that affect visual representation of the
+ * paragraph.
+ */
+ ParagraphAttributes paragraphAttributes{};
+
+ /*
+ * Defines can the text be selected (and copied) or not.
+ */
+ bool isSelectable{};
+
+ bool onTextLayout{};
+
+ /*
+ * Defines the color of the selection highlight.
+ * [Windows]
+ */
+ std::optional selectionColor{};
+
+#pragma mark - DebugStringConvertible
+
+#if RN_DEBUG_STRING_CONVERTIBLE
+ SharedDebugStringConvertibleList getDebugProps() const override;
+#endif
+};
+
+} // namespace facebook::react
diff --git a/vnext/overrides.json b/vnext/overrides.json
index b116ceb1b22..63418e0e52c 100644
--- a/vnext/overrides.json
+++ b/vnext/overrides.json
@@ -159,6 +159,20 @@
"baseHash": "7fdf1967fa9c3421b11e841afcf207624df18706",
"issue": 15379
},
+ {
+ "type": "derived",
+ "file": "ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/text/BaseParagraphProps.cpp",
+ "baseFile": "packages/react-native/ReactCommon/react/renderer/components/text/BaseParagraphProps.cpp",
+ "baseHash": "1aaf0a003c83195882c512a664409e429de4f892",
+ "issue": 15552
+ },
+ {
+ "type": "derived",
+ "file": "ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/text/BaseParagraphProps.h",
+ "baseFile": "packages/react-native/ReactCommon/react/renderer/components/text/BaseParagraphProps.h",
+ "baseHash": "7661ba5c8392034cbda48f5d4b721a1ff30fe68d",
+ "issue": 15552
+ },
{
"type": "patch",
"file": "ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/text/ParagraphShadowNode.cpp",