mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Add "Text Styles" TextInput Example
Summary: This adds a series of examples for TextInput styles to screenshot test, specifically the ones which are projected to Android as spans. This will be used in refactoring to verify we do not change visual output. Changelog: [Internal][Added] - Add "Text Styles" TextInput Example Reviewed By: cortinico Differential Revision: D43158004 fbshipit-source-id: adaecf0e37941e66e280db282e2631a95b08b27a
This commit is contained in:
committed by
Facebook GitHub Bot
parent
d147bbbe84
commit
817948e0aa
@@ -18,6 +18,7 @@ import type {PressEvent} from 'react-native/Libraries/Types/CoreEventTypes';
|
||||
|
||||
type Props = $ReadOnly<{|
|
||||
testID?: string,
|
||||
textTestID?: string,
|
||||
children?: React.Node,
|
||||
onPress?: ?(event: PressEvent) => mixed,
|
||||
|}>;
|
||||
@@ -30,7 +31,7 @@ class RNTesterButton extends React.Component<Props> {
|
||||
onPress={this.props.onPress}
|
||||
style={styles.button}
|
||||
underlayColor="grey">
|
||||
<Text>{this.props.children}</Text>
|
||||
<Text testID={this.props.textTestID}>{this.props.children}</Text>
|
||||
</TouchableHighlight>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -10,17 +10,20 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
const React = require('react');
|
||||
|
||||
const {
|
||||
import * as React from 'react';
|
||||
import {useContext, useState} from 'react';
|
||||
import {
|
||||
Button,
|
||||
Platform,
|
||||
Text,
|
||||
TextInput,
|
||||
View,
|
||||
StyleSheet,
|
||||
} = require('react-native');
|
||||
} from 'react-native';
|
||||
import type {TextStyle} from 'react-native/Libraries/StyleSheet/StyleSheet';
|
||||
|
||||
import RNTesterButton from '../../components/RNTesterButton';
|
||||
import {RNTesterThemeContext} from '../../components/RNTesterTheme';
|
||||
import type {RNTesterModuleExample} from '../../types/RNTesterTypes';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
@@ -49,9 +52,10 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
label: {
|
||||
width: 115,
|
||||
alignItems: 'flex-end',
|
||||
textAlign: 'right',
|
||||
marginRight: 10,
|
||||
paddingTop: 2,
|
||||
fontSize: 12,
|
||||
},
|
||||
inputContainer: {
|
||||
flex: 1,
|
||||
@@ -80,15 +84,20 @@ const styles = StyleSheet.create({
|
||||
fontSize: 13,
|
||||
padding: 4,
|
||||
},
|
||||
screenshotArea: {
|
||||
position: 'absolute',
|
||||
top: -5,
|
||||
left: 120,
|
||||
right: -5,
|
||||
bottom: -5,
|
||||
},
|
||||
});
|
||||
|
||||
class WithLabel extends React.Component<$FlowFixMeProps> {
|
||||
render(): React.Node {
|
||||
return (
|
||||
<View style={styles.labelContainer}>
|
||||
<View style={styles.label}>
|
||||
<Text>{this.props.label}</Text>
|
||||
</View>
|
||||
<Text style={styles.label}>{this.props.label}</Text>
|
||||
<View style={styles.inputContainer}>{this.props.children}</View>
|
||||
</View>
|
||||
);
|
||||
@@ -592,6 +601,239 @@ function UncontrolledExample() {
|
||||
);
|
||||
}
|
||||
|
||||
const TextStylesExample = React.memo(() => {
|
||||
const theme = useContext(RNTesterThemeContext);
|
||||
|
||||
return (
|
||||
<TextStylesContainer
|
||||
examples={[
|
||||
{
|
||||
name: 'backgroundColor',
|
||||
textStyles: [
|
||||
{backgroundColor: theme.SystemBackgroundColor},
|
||||
{backgroundColor: 'red'},
|
||||
{backgroundColor: 'orange'},
|
||||
{backgroundColor: 'yellow'},
|
||||
{backgroundColor: 'green'},
|
||||
{backgroundColor: 'blue'},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'color',
|
||||
textStyles: [
|
||||
{color: theme.LabelColor},
|
||||
{color: 'red'},
|
||||
{color: 'orange'},
|
||||
{color: 'yellow'},
|
||||
{color: 'green'},
|
||||
{color: 'blue'},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'fontFamily',
|
||||
textStyles: [
|
||||
{fontFamily: 'sans-serif'},
|
||||
{fontFamily: 'serif'},
|
||||
{fontFamily: 'monospace'},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'fontSize',
|
||||
textStyles: [
|
||||
{fontSize: 8},
|
||||
{fontSize: 10},
|
||||
{fontSize: 12},
|
||||
{fontSize: 14},
|
||||
{fontSize: 16},
|
||||
{fontSize: 18},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'fontStyle',
|
||||
textStyles: [{fontStyle: 'normal'}, {fontStyle: 'italic'}],
|
||||
},
|
||||
{
|
||||
name: 'fontWeight',
|
||||
textStyles: [
|
||||
{fontWeight: 'normal'},
|
||||
{fontWeight: 'bold'},
|
||||
{fontWeight: '200'},
|
||||
{fontWeight: '400'},
|
||||
{fontWeight: '600'},
|
||||
{fontWeight: '800'},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'letterSpacing',
|
||||
textStyles: [
|
||||
{letterSpacing: 0},
|
||||
{letterSpacing: 1},
|
||||
{letterSpacing: 2},
|
||||
{letterSpacing: 3},
|
||||
{letterSpacing: 4},
|
||||
{letterSpacing: 5},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'lineHeight',
|
||||
multiline: true,
|
||||
textStyles: [
|
||||
{lineHeight: 4},
|
||||
{lineHeight: 8},
|
||||
{lineHeight: 16},
|
||||
{lineHeight: 24},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'textDecorationLine',
|
||||
textStyles: [
|
||||
{textDecorationLine: 'none'},
|
||||
{textDecorationLine: 'underline'},
|
||||
{textDecorationLine: 'line-through'},
|
||||
{textDecorationLine: 'underline line-through'},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'textShadow',
|
||||
textStyles: [
|
||||
{
|
||||
textShadowColor: 'black',
|
||||
textShadowOffset: {width: 0, height: 0},
|
||||
textShadowRadius: 0,
|
||||
},
|
||||
{
|
||||
textShadowColor: 'black',
|
||||
textShadowOffset: {width: 0, height: 0},
|
||||
textShadowRadius: 5,
|
||||
},
|
||||
{
|
||||
textShadowColor: 'red',
|
||||
textShadowOffset: {width: 0, height: 0},
|
||||
textShadowRadius: 5,
|
||||
},
|
||||
{
|
||||
textShadowColor: 'blue',
|
||||
textShadowOffset: {width: 0, height: -5},
|
||||
textShadowRadius: 5,
|
||||
},
|
||||
{
|
||||
textShadowColor: 'green',
|
||||
textShadowOffset: {width: 0, height: 5},
|
||||
textShadowRadius: 5,
|
||||
},
|
||||
{
|
||||
textShadowColor: 'orange',
|
||||
textShadowOffset: {width: 10, height: 0},
|
||||
textShadowRadius: 5,
|
||||
},
|
||||
],
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
type TextStylesContainerProps = {
|
||||
examples: $ReadOnlyArray<{
|
||||
name: string,
|
||||
textStyles: $ReadOnlyArray<TextStyle>,
|
||||
multiline?: boolean,
|
||||
}>,
|
||||
};
|
||||
|
||||
function TextStylesContainer({examples}: TextStylesContainerProps) {
|
||||
const [offset, setOffset] = useState(0);
|
||||
|
||||
const MAX_CYCLES = 6;
|
||||
|
||||
return (
|
||||
<View>
|
||||
<RNTesterButton
|
||||
testID="cycle-styles"
|
||||
textTestID="cycle-styles-label"
|
||||
onPress={() => setOffset((offset + 1) % MAX_CYCLES)}>
|
||||
Cycle {offset + 1}/{MAX_CYCLES}
|
||||
</RNTesterButton>
|
||||
<View>
|
||||
<View testID="styles-screenshot-area" style={styles.screenshotArea} />
|
||||
{examples.map(({name, multiline, textStyles}) => (
|
||||
<WithLabel label={name} key={name}>
|
||||
{multiline ? (
|
||||
<MultilineStyledTextInput
|
||||
name={name}
|
||||
textStyles={textStyles}
|
||||
styleOffset={offset}
|
||||
/>
|
||||
) : (
|
||||
<StyledTextInput
|
||||
name={name}
|
||||
textStyles={textStyles}
|
||||
styleOffset={offset}
|
||||
/>
|
||||
)}
|
||||
</WithLabel>
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
type StyledTextInputProps = {
|
||||
name: string,
|
||||
textStyles: $ReadOnlyArray<TextStyle>,
|
||||
styleOffset: number,
|
||||
};
|
||||
|
||||
function StyledTextInput({
|
||||
name,
|
||||
textStyles,
|
||||
styleOffset,
|
||||
}: StyledTextInputProps) {
|
||||
return (
|
||||
<TextInput
|
||||
style={[
|
||||
styles.default,
|
||||
textStyles[(0 + styleOffset) % textStyles.length],
|
||||
]}
|
||||
testID={`style-${name}`}>
|
||||
<Text>He</Text>
|
||||
<Text style={textStyles[(1 + styleOffset) % textStyles.length]}>ll</Text>
|
||||
<Text style={textStyles[(2 + styleOffset) % textStyles.length]}>
|
||||
o,
|
||||
<Text style={textStyles[(0 + styleOffset) % textStyles.length]}> </Text>
|
||||
</Text>
|
||||
<Text style={textStyles[(3 + styleOffset) % textStyles.length]}>Wo</Text>
|
||||
<Text style={textStyles[(4 + styleOffset) % textStyles.length]}>rl</Text>
|
||||
<Text style={textStyles[(5 + styleOffset) % textStyles.length]}>d!</Text>
|
||||
</TextInput>
|
||||
);
|
||||
}
|
||||
|
||||
function MultilineStyledTextInput({
|
||||
name,
|
||||
textStyles,
|
||||
styleOffset,
|
||||
}: StyledTextInputProps) {
|
||||
return (
|
||||
<TextInput
|
||||
multiline={true}
|
||||
style={[
|
||||
styles.default,
|
||||
textStyles[(0 + styleOffset) % textStyles.length],
|
||||
]}
|
||||
testID={`style-${name}`}>
|
||||
<Text>Hel{'\n'}</Text>
|
||||
<Text style={textStyles[(1 + styleOffset) % textStyles.length]}>
|
||||
lo {'\n'}
|
||||
</Text>
|
||||
<Text style={textStyles[(2 + styleOffset) % textStyles.length]}>
|
||||
Wor{'\n'}
|
||||
</Text>
|
||||
<Text style={textStyles[(3 + styleOffset) % textStyles.length]}>ld!</Text>
|
||||
</TextInput>
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = ([
|
||||
{
|
||||
title: 'Auto-focus',
|
||||
@@ -867,8 +1109,11 @@ module.exports = ([
|
||||
{
|
||||
title: 'Uncontrolled component with layout changes',
|
||||
name: 'uncontrolledComponent',
|
||||
render: function (): React.Node {
|
||||
return <UncontrolledExample />;
|
||||
},
|
||||
render: () => <UncontrolledExample />,
|
||||
},
|
||||
{
|
||||
title: 'Text styles',
|
||||
name: 'textStyles',
|
||||
render: () => <TextStylesExample />,
|
||||
},
|
||||
]: Array<RNTesterModuleExample>);
|
||||
|
||||
Reference in New Issue
Block a user