mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Summary: The `maxFontSizeMultiplier` prop for `Text` and `TextInput` was not handled in Fabric / New Architecture as documented in https://github.com/facebook/react-native/issues/47499. bypass-github-export-checks ## Changelog: [GENERAL] [FIXED] - Fix `maxFontSizeMultiplier` prop on `Text` and `TextInput` components in Fabric / New Architecture Pull Request resolved: https://github.com/facebook/react-native/pull/47614 Test Plan: I have not added any automated tests for this change but try to do so if requested. I have however added examples to RN Tester for both the Text and TextInput components, as well as compared the behaviour with Paper / Old Architecture. Both on version 0.76. Noticed now I didn't do exactly the same steps in both videos, oops! Be aware that reapplying changes made in the Settings are currently half-broken on the new architecture, thus I'm restarting the app on Android and iOS. But this issue is unrelated to my changes. I've tested on main branch and it has the same issue. Here are comparison videos between Paper and Fabric on iOS *after* I've made my fix. ### Text | Paper | Fabric | | ------------- | ------------- | | <video src="https://github.com/user-attachments/assets/f4fd009f-aa6d-41ab-92fa-8dcf1e351ba1" /> | <video src="https://github.com/user-attachments/assets/fda42cc6-34c2-42a7-a6e2-028e7c866075" /> | ### TextInput | Paper | Fabric | | ------------- | ------------- | | <video src="https://github.com/user-attachments/assets/59b59f7b-25d2-4b5b-a8e2-d2054cc6390b" /> | <video src="https://github.com/user-attachments/assets/72068566-8f2a-4463-874c-45a6f5b63b0d" /> | Reviewed By: Abbondanzo Differential Revision: D65953019 Pulled By: cipolleschi fbshipit-source-id: 90c3c7e236229e9ad9bd346941fafe4af8a9d9fc
461 lines
12 KiB
JavaScript
461 lines
12 KiB
JavaScript
/**
|
|
* 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.
|
|
*
|
|
* @format
|
|
* @flow strict-local
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
import type {
|
|
RNTesterModule,
|
|
RNTesterModuleExample,
|
|
} from '../../types/RNTesterTypes';
|
|
|
|
import ExampleTextInput from './ExampleTextInput';
|
|
import TextInputSharedExamples from './TextInputSharedExamples';
|
|
import React from 'react';
|
|
import {StyleSheet, Text, View} from 'react-native';
|
|
|
|
const ToggleDefaultPaddingExample = (): React.Node => {
|
|
const [hasPadding, setHasPadding] = React.useState(false);
|
|
|
|
return (
|
|
<View>
|
|
<ExampleTextInput style={hasPadding ? {padding: 0} : null} />
|
|
<Text onPress={() => setHasPadding(!hasPadding)}>Toggle padding</Text>
|
|
</View>
|
|
);
|
|
};
|
|
|
|
const styles = StyleSheet.create({
|
|
multiline: {
|
|
height: 60,
|
|
fontSize: 16,
|
|
},
|
|
singleLine: {
|
|
fontSize: 16,
|
|
},
|
|
singleLineWithHeightTextInput: {
|
|
height: 30,
|
|
},
|
|
wrappedText: {
|
|
maxWidth: 300,
|
|
},
|
|
});
|
|
|
|
const examples: Array<RNTesterModuleExample> = [
|
|
...TextInputSharedExamples,
|
|
{
|
|
title: 'Colors and text inputs',
|
|
render: function (): React.Node {
|
|
return (
|
|
<View>
|
|
<ExampleTextInput
|
|
style={[styles.singleLine]}
|
|
defaultValue="Default color text"
|
|
/>
|
|
<ExampleTextInput
|
|
style={[styles.singleLine, {color: 'green'}]}
|
|
defaultValue="Green Text"
|
|
/>
|
|
<ExampleTextInput
|
|
placeholder="Default placeholder text color"
|
|
style={styles.singleLine}
|
|
/>
|
|
<ExampleTextInput
|
|
placeholder="Red placeholder text color"
|
|
placeholderTextColor="red"
|
|
style={styles.singleLine}
|
|
/>
|
|
<ExampleTextInput
|
|
placeholder="Default underline color"
|
|
style={styles.singleLine}
|
|
/>
|
|
<ExampleTextInput
|
|
placeholder="Blue underline color"
|
|
style={styles.singleLine}
|
|
underlineColorAndroid="blue"
|
|
/>
|
|
<ExampleTextInput
|
|
defaultValue="Same BackgroundColor as View "
|
|
style={[
|
|
styles.singleLine,
|
|
{backgroundColor: 'rgba(100, 100, 100, 0.3)'},
|
|
]}>
|
|
<Text style={{backgroundColor: 'rgba(100, 100, 100, 0.3)'}}>
|
|
Darker backgroundColor
|
|
</Text>
|
|
</ExampleTextInput>
|
|
<ExampleTextInput
|
|
defaultValue="Selection Color is red"
|
|
selectionColor={'red'}
|
|
style={styles.singleLine}
|
|
/>
|
|
<ExampleTextInput
|
|
defaultValue="Selection handles are red"
|
|
selectionHandleColor={'red'}
|
|
style={styles.singleLine}
|
|
/>
|
|
<ExampleTextInput
|
|
defaultValue="Cursor Color is red"
|
|
cursorColor={'red'}
|
|
style={styles.singleLine}
|
|
/>
|
|
</View>
|
|
);
|
|
},
|
|
},
|
|
{
|
|
title: 'Font Weight',
|
|
render: function (): React.Node {
|
|
return (
|
|
<View>
|
|
<ExampleTextInput
|
|
defaultValue="Font Weight (default)"
|
|
style={[styles.singleLine]}
|
|
/>
|
|
{[
|
|
'normal',
|
|
'bold',
|
|
'900',
|
|
800,
|
|
'700',
|
|
'600',
|
|
'500',
|
|
'400',
|
|
'300',
|
|
'200',
|
|
'100',
|
|
].map(fontWeight => (
|
|
<ExampleTextInput
|
|
defaultValue={`Font Weight (${fontWeight})`}
|
|
key={fontWeight}
|
|
style={[styles.singleLine, {fontWeight}]}
|
|
/>
|
|
))}
|
|
</View>
|
|
);
|
|
},
|
|
},
|
|
{
|
|
title: 'Text input, themes and heights',
|
|
render: function (): React.Node {
|
|
return (
|
|
<ExampleTextInput
|
|
placeholder="If you set height, beware of padding set from themes"
|
|
style={[styles.singleLineWithHeightTextInput]}
|
|
/>
|
|
);
|
|
},
|
|
},
|
|
{
|
|
title: 'letterSpacing',
|
|
render: function (): React.Node {
|
|
return (
|
|
<View>
|
|
<ExampleTextInput
|
|
style={[styles.singleLine, {letterSpacing: 0}]}
|
|
placeholder="letterSpacing = 0"
|
|
/>
|
|
<ExampleTextInput
|
|
style={[styles.singleLine, {letterSpacing: 2}]}
|
|
placeholder="letterSpacing = 2"
|
|
/>
|
|
<ExampleTextInput
|
|
style={[styles.singleLine, {letterSpacing: 9}]}
|
|
placeholder="letterSpacing = 9"
|
|
/>
|
|
<ExampleTextInput
|
|
style={[styles.singleLine, {letterSpacing: -1}]}
|
|
placeholder="letterSpacing = -1"
|
|
/>
|
|
</View>
|
|
);
|
|
},
|
|
},
|
|
{
|
|
title: 'Passwords',
|
|
render: function (): React.Node {
|
|
return (
|
|
<View>
|
|
<ExampleTextInput
|
|
defaultValue="iloveturtles"
|
|
secureTextEntry={true}
|
|
style={styles.singleLine}
|
|
/>
|
|
<ExampleTextInput
|
|
secureTextEntry={true}
|
|
style={[styles.singleLine, {color: 'red'}]}
|
|
placeholder="color is supported too"
|
|
placeholderTextColor="red"
|
|
/>
|
|
</View>
|
|
);
|
|
},
|
|
},
|
|
{
|
|
title: 'Editable',
|
|
render: function (): React.Node {
|
|
return (
|
|
<ExampleTextInput
|
|
defaultValue="Can't touch this! (>'-')> ^(' - ')^ <('-'<) (>'-')> ^(' - ')^"
|
|
editable={false}
|
|
style={styles.singleLine}
|
|
/>
|
|
);
|
|
},
|
|
},
|
|
{
|
|
title: 'Multiline',
|
|
render: function (): React.Node {
|
|
return (
|
|
<View>
|
|
<ExampleTextInput
|
|
autoCorrect={true}
|
|
placeholder="multiline, aligned top-left"
|
|
placeholderTextColor="red"
|
|
multiline={true}
|
|
style={[
|
|
styles.multiline,
|
|
{textAlign: 'left', textAlignVertical: 'top'},
|
|
]}
|
|
/>
|
|
<ExampleTextInput
|
|
autoCorrect={true}
|
|
placeholder="multiline, aligned center"
|
|
placeholderTextColor="green"
|
|
multiline={true}
|
|
style={[
|
|
styles.multiline,
|
|
{textAlign: 'center', textAlignVertical: 'center'},
|
|
]}
|
|
/>
|
|
<ExampleTextInput
|
|
autoCorrect={true}
|
|
multiline={true}
|
|
style={[
|
|
styles.multiline,
|
|
{color: 'blue'},
|
|
{textAlign: 'right', textAlignVertical: 'bottom'},
|
|
]}>
|
|
<Text style={styles.multiline}>
|
|
multiline with children, aligned bottom-right
|
|
</Text>
|
|
</ExampleTextInput>
|
|
</View>
|
|
);
|
|
},
|
|
},
|
|
{
|
|
title: 'Editable and Read only',
|
|
render: function (): React.Node {
|
|
return (
|
|
<View>
|
|
<ExampleTextInput
|
|
placeholder="editable text input using editable prop"
|
|
editable
|
|
/>
|
|
<ExampleTextInput
|
|
placeholder="uneditable text input using editable prop"
|
|
editable={false}
|
|
/>
|
|
<ExampleTextInput
|
|
placeholder="editable text input using readOnly prop"
|
|
readOnly={false}
|
|
/>
|
|
<ExampleTextInput
|
|
placeholder="uneditable text input using readOnly prop"
|
|
readOnly
|
|
/>
|
|
</View>
|
|
);
|
|
},
|
|
},
|
|
{
|
|
title: 'Fixed number of lines',
|
|
platform: 'android',
|
|
render: function (): React.Node {
|
|
return (
|
|
<View style={styles.wrappedText}>
|
|
<ExampleTextInput
|
|
numberOfLines={2}
|
|
multiline={true}
|
|
placeholder="Two line input using numberOfLines prop"
|
|
/>
|
|
<ExampleTextInput
|
|
numberOfLines={5}
|
|
multiline={true}
|
|
placeholder="Five line input using numberOfLines prop"
|
|
/>
|
|
<ExampleTextInput
|
|
rows={2}
|
|
multiline={true}
|
|
placeholder="Two line input using rows prop"
|
|
/>
|
|
<ExampleTextInput
|
|
rows={5}
|
|
multiline={true}
|
|
placeholder="Five line input using rows prop"
|
|
/>
|
|
</View>
|
|
);
|
|
},
|
|
},
|
|
{
|
|
title: 'allowFontScaling attribute',
|
|
render: function (): React.Node {
|
|
return (
|
|
<View>
|
|
<Text>
|
|
By default, text will respect Text Size accessibility setting on
|
|
Android. It means that all font sizes will be increased or decreased
|
|
depending on the value of the Text Size setting in the OS's Settings
|
|
app.
|
|
</Text>
|
|
<ExampleTextInput
|
|
placeholder="allowFontScaling = false"
|
|
allowFontScaling={false}
|
|
/>
|
|
<ExampleTextInput
|
|
style={{marginTop: 10}}
|
|
placeholder="allowFontScaling = false"
|
|
allowFontScaling={true}
|
|
/>
|
|
</View>
|
|
);
|
|
},
|
|
},
|
|
{
|
|
title: 'maxFontSizeMultiplier attribute',
|
|
name: 'maxFontSizeMultiplier',
|
|
render(): React.Node {
|
|
return (
|
|
<View testID={'max-font-size-multiplier'}>
|
|
<Text>
|
|
When allowFontScaling is enabled, you can use the
|
|
maxFontSizeMultiplier prop to set an upper limit on how much the
|
|
font size will be scaled.
|
|
</Text>
|
|
<ExampleTextInput
|
|
allowFontScaling={true}
|
|
maxFontSizeMultiplier={1}
|
|
placeholder="This text will not scale up (max 1x)"
|
|
style={{marginTop: 10}}
|
|
testID={'non-scalable-text-input'}
|
|
/>
|
|
<ExampleTextInput
|
|
allowFontScaling={true}
|
|
maxFontSizeMultiplier={1.5}
|
|
placeholder="This text will scale up (max 1.5x)"
|
|
style={{marginTop: 10}}
|
|
testID={'scalable-text-input'}
|
|
/>
|
|
</View>
|
|
);
|
|
},
|
|
},
|
|
{
|
|
title: 'Text Auto Complete',
|
|
render: function (): React.Node {
|
|
return (
|
|
<View>
|
|
<ExampleTextInput autoComplete="country" placeholder="country" />
|
|
<ExampleTextInput
|
|
autoComplete="postal-address-country"
|
|
placeholder="postal-address-country"
|
|
/>
|
|
<ExampleTextInput
|
|
autoComplete="one-time-code"
|
|
placeholder="one-time-code"
|
|
/>
|
|
<ExampleTextInput autoComplete="sms-otp" placeholder="sms-otp" />
|
|
</View>
|
|
);
|
|
},
|
|
},
|
|
{
|
|
title: 'Return key',
|
|
render: function (): React.Node {
|
|
const returnKeyTypes = [
|
|
'none',
|
|
'go',
|
|
'search',
|
|
'send',
|
|
'done',
|
|
'previous',
|
|
'next',
|
|
];
|
|
const returnKeyLabels = ['Compile', 'React Native'];
|
|
const returnKeyExamples = returnKeyTypes.map(type => {
|
|
return (
|
|
<ExampleTextInput
|
|
key={type}
|
|
returnKeyType={type}
|
|
placeholder={'returnKeyType: ' + type}
|
|
style={styles.singleLine}
|
|
/>
|
|
);
|
|
});
|
|
const types = returnKeyLabels.map(type => {
|
|
return (
|
|
<ExampleTextInput
|
|
key={type}
|
|
returnKeyLabel={type}
|
|
placeholder={'returnKeyLabel: ' + type}
|
|
style={styles.singleLine}
|
|
/>
|
|
);
|
|
});
|
|
return (
|
|
<View>
|
|
{returnKeyExamples}
|
|
{types}
|
|
</View>
|
|
);
|
|
},
|
|
},
|
|
{
|
|
title: 'Inline Images',
|
|
render: function (): React.Node {
|
|
return (
|
|
<View>
|
|
<ExampleTextInput
|
|
inlineImageLeft="ic_menu_black_24dp"
|
|
placeholder="This has drawableLeft set"
|
|
style={styles.singleLine}
|
|
/>
|
|
<ExampleTextInput
|
|
inlineImageLeft="ic_menu_black_24dp"
|
|
inlineImagePadding={30}
|
|
placeholder="This has drawableLeft and drawablePadding set"
|
|
style={styles.singleLine}
|
|
/>
|
|
<ExampleTextInput
|
|
placeholder="This does not have drawable props set"
|
|
style={styles.singleLine}
|
|
/>
|
|
</View>
|
|
);
|
|
},
|
|
},
|
|
{
|
|
title: 'Toggle Default Padding',
|
|
render: function (): React.Node {
|
|
return <ToggleDefaultPaddingExample />;
|
|
},
|
|
},
|
|
];
|
|
|
|
module.exports = ({
|
|
displayName: (undefined: ?string),
|
|
title: 'TextInput',
|
|
documentationURL: 'https://reactnative.dev/docs/textinput',
|
|
category: 'Basic',
|
|
description: 'Single and multi-line text inputs.',
|
|
examples,
|
|
}: RNTesterModule);
|