From 23f1b030577b8a98d886c6ca2fa7c9bb5c319f96 Mon Sep 17 00:00:00 2001 From: Collin Schneide <27441618+FaithfulAudio@users.noreply.github.com> Date: Sat, 18 Jul 2026 19:53:39 +0800 Subject: [PATCH 1/2] fix(textinput): correct placeholder layout constraints (px vs DIP) and no-op NaN fontSize guard Forward-port of #16303 (0.83-stable) to main. CreatePlaceholderLayout fed m_imgWidth/m_imgHeight - which are physical pixels (frame * pointScaleFactor) - into LayoutConstraints, which are expressed in DIPs. The placeholder was laid out in a box pointScaleFactor times too large, so it measured and positioned at a different height than the typed text. Divide by pointScaleFactor. The NaN fontSize guard was also a no-op: it evaluated defaultTextAttributes().fontSize as a discarded expression statement instead of assigning it, so a placeholder with no fontSize never picked up the default. --- .../TextInput/WindowsTextInputComponentView.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp index 91ae1551daf..a8af925e960 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp @@ -1743,7 +1743,7 @@ winrt::com_ptr<::IDWriteTextLayout> WindowsTextInputComponentView::CreatePlaceho const auto &props = windowsTextInputProps(); facebook::react::TextAttributes textAttributes = props.textAttributes; if (std::isnan(props.textAttributes.fontSize)) { - facebook::react::TextAttributes::defaultTextAttributes().fontSize; + textAttributes.fontSize = facebook::react::TextAttributes::defaultTextAttributes().fontSize; } textAttributes.fontSizeMultiplier = m_fontSizeMultiplier; fragment1.string = props.placeholder; @@ -1751,8 +1751,12 @@ winrt::com_ptr<::IDWriteTextLayout> WindowsTextInputComponentView::CreatePlaceho attributedString.appendFragment(std::move(fragment1)); facebook::react::LayoutConstraints constraints; - constraints.maximumSize.width = static_cast(m_imgWidth); - constraints.maximumSize.height = static_cast(m_imgHeight); + // m_imgWidth/m_imgHeight are physical pixels (frame * pointScaleFactor), but + // LayoutConstraints are expressed in DIPs. Feeding physical px laid the + // placeholder out in a box pointScaleFactor x too large, so the placeholder was + // measured/positioned at a different height than the typed text. Convert to DIPs. + constraints.maximumSize.width = static_cast(m_imgWidth) / m_layoutMetrics.pointScaleFactor; + constraints.maximumSize.height = static_cast(m_imgHeight) / m_layoutMetrics.pointScaleFactor; facebook::react::WindowsTextLayoutManager::GetTextLayout( facebook::react::AttributedStringBox(attributedString), {} /*TODO*/, constraints, textLayout); From c8537041ba6ccdcd1e76840472835dc1551aed42 Mon Sep 17 00:00:00 2001 From: Collin Schneide <27441618+FaithfulAudio@users.noreply.github.com> Date: Sat, 18 Jul 2026 19:53:41 +0800 Subject: [PATCH 2/2] add beachball change file --- ...eact-native-windows-fix-textinput-placeholder-main.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 change/react-native-windows-fix-textinput-placeholder-main.json diff --git a/change/react-native-windows-fix-textinput-placeholder-main.json b/change/react-native-windows-fix-textinput-placeholder-main.json new file mode 100644 index 00000000000..b759d12c2d5 --- /dev/null +++ b/change/react-native-windows-fix-textinput-placeholder-main.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "Fix placeholder layout constraints fed physical px instead of DIPs; fix no-op NaN fontSize guard in CreatePlaceholderLayout", + "packageName": "react-native-windows", + "email": "collindanielschneide@gmail.com", + "dependentChangeType": "patch" +}