Skip to content

Commit a962aa4

Browse files
Apply baseline-offset compensation to TextInput placeholder
The placeholder in RCTUITextField (single-line) and RCTUITextView (multi-line) inherits the paragraph style from `defaultTextAttributes`, so it suffers the same bottom-anchor misalignment as typed text when `lineHeight > fontSize`. Apply the equivalent `NSBaselineOffsetAttributeName` in `_placeholderTextAttributes` so the placeholder renders at the same vertical position as typed text. These backing views are shared between Paper and Fabric, so this also fixes the placeholder on the old arch (where the existing fix in facebook#38359 only addressed typed text). Also simplify the RN Tester example to a single-line + multi-line pair at fontSize 16 / lineHeight 32 — enough to demonstrate the regression and the fix for both control types.
1 parent f864b61 commit a962aa4

3 files changed

Lines changed: 30 additions & 23 deletions

File tree

packages/react-native/Libraries/Text/TextInput/Multiline/RCTUITextView.mm

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,12 @@ - (void)_updatePlaceholder
364364
[textAttributes setValue:defaultPlaceholderFont() forKey:NSFontAttributeName];
365365
}
366366

367+
NSParagraphStyle *paragraphStyle = textAttributes[NSParagraphStyleAttributeName];
368+
UIFont *font = textAttributes[NSFontAttributeName];
369+
if (paragraphStyle && font && paragraphStyle.maximumLineHeight > font.lineHeight) {
370+
textAttributes[NSBaselineOffsetAttributeName] = @((paragraphStyle.maximumLineHeight - font.lineHeight) / 2.0);
371+
}
372+
367373
return textAttributes;
368374
}
369375

packages/react-native/Libraries/Text/TextInput/Singleline/RCTUITextField.mm

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,12 @@ - (void)setDisableKeyboardShortcuts:(BOOL)disableKeyboardShortcuts
169169
[textAttributes removeObjectForKey:NSForegroundColorAttributeName];
170170
}
171171

172+
NSParagraphStyle *paragraphStyle = textAttributes[NSParagraphStyleAttributeName];
173+
UIFont *font = textAttributes[NSFontAttributeName];
174+
if (paragraphStyle && font && paragraphStyle.maximumLineHeight > font.lineHeight) {
175+
textAttributes[NSBaselineOffsetAttributeName] = @((paragraphStyle.maximumLineHeight - font.lineHeight) / 2.0);
176+
}
177+
172178
return textAttributes;
173179
}
174180

packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1189,33 +1189,28 @@ module.exports = [
11891189
render: () => <TextStylesExample />,
11901190
},
11911191
{
1192-
title: 'Single-line lineHeight baseline',
1192+
title: 'lineHeight baseline',
11931193
name: 'lineHeightBaseline',
1194-
description:
1195-
'Regression repro for https://github.com/facebook/react-native/issues/39145. ' +
1196-
'When lineHeight > fontSize on a single-line TextInput, typed text should ' +
1197-
'stay vertically centered. Placeholder centering is already correct; the ' +
1198-
'bug is that typed glyphs anchor to the bottom of the attributed-string ' +
1199-
'line box, appearing visually too low.',
12001194
render: function (): React.Node {
1195+
const inputStyle = {
1196+
fontSize: 16,
1197+
lineHeight: 32,
1198+
borderColor: '#ccc',
1199+
borderWidth: 1,
1200+
padding: 8,
1201+
};
12011202
return (
12021203
<View>
1203-
{[20, 24, 32, 48].map(lineHeight => (
1204-
<WithLabel
1205-
key={lineHeight}
1206-
label={`fontSize: 16, lineHeight: ${lineHeight}`}>
1207-
<ExampleTextInput
1208-
placeholder="placeholder stays centered"
1209-
style={{
1210-
fontSize: 16,
1211-
lineHeight,
1212-
borderColor: '#ccc',
1213-
borderWidth: 1,
1214-
padding: 8,
1215-
}}
1216-
/>
1217-
</WithLabel>
1218-
))}
1204+
<WithLabel label="single-line">
1205+
<ExampleTextInput placeholder="placeholder" style={inputStyle} />
1206+
</WithLabel>
1207+
<WithLabel label="multi-line">
1208+
<ExampleTextInput
1209+
multiline
1210+
placeholder="placeholder"
1211+
style={inputStyle}
1212+
/>
1213+
</WithLabel>
12191214
</View>
12201215
);
12211216
},

0 commit comments

Comments
 (0)