/**
* 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.
*
* @flow strict-local
* @format
*/
'use strict';
import type {RNTesterModule} from '../../types/RNTesterTypes';
import hotdog from '../../assets/hotdog.jpg';
import RNTesterText from '../../components/RNTesterText';
import TextLegend from '../../components/TextLegend';
import TextAdjustsDynamicLayoutExample from './TextAdjustsDynamicLayoutExample';
import TextSharedExamples from './TextSharedExamples';
const TextInlineView = require('../../components/TextInlineView');
const React = require('react');
const {
Image,
LayoutAnimation,
StyleSheet,
Text,
TextInput,
View,
} = require('react-native');
class Entity extends React.Component<{children: React.Node}> {
render(): React.Node {
return (
{this.props.children}
);
}
}
class AttributeToggler extends React.Component<{...}, $FlowFixMe> {
state: {fontSize: number, fontWeight: 'bold' | 'normal'} = {
fontWeight: 'bold',
fontSize: 15,
};
toggleWeight = () => {
this.setState({
fontWeight: this.state.fontWeight === 'bold' ? 'normal' : 'bold',
});
};
increaseSize = () => {
this.setState({
fontSize: this.state.fontSize + 1,
});
};
render(): React.Node {
const curStyle = {
fontWeight: this.state.fontWeight,
fontSize: this.state.fontSize,
};
return (
Tap the controls below to change attributes.
See how it will even work on{' '}
this nested RNTesterText
Toggle Weight
Increase Size
);
}
}
type AdjustingFontSizeProps = $ReadOnly<{}>;
type AdjustingFontSizeState = {
dynamicText: string,
shouldRender: boolean,
};
class AdjustingFontSize extends React.Component<
AdjustingFontSizeProps,
AdjustingFontSizeState,
> {
state: AdjustingFontSizeState = {
dynamicText: '',
shouldRender: true,
};
reset = () => {
LayoutAnimation.easeInEaseOut();
this.setState({
shouldRender: false,
});
setTimeout(() => {
LayoutAnimation.easeInEaseOut();
this.setState({
dynamicText: '',
shouldRender: true,
});
}, 300);
};
addText = () => {
this.setState({
dynamicText:
this.state.dynamicText +
(Math.floor((Math.random() * 10) % 2) ? ' foo' : ' bar'),
});
};
removeText = () => {
this.setState({
dynamicText: this.state.dynamicText.slice(
0,
this.state.dynamicText.length - 4,
),
});
};
render(): React.Node {
if (!this.state.shouldRender) {
return ;
}
return (
Truncated text is baaaaad.
Shrinking to fit available space is much better!
{'Add text to me to watch me shrink!' + ' ' + this.state.dynamicText}
{'Multiline text component shrinking is supported, watch as this reeeeaaaally loooooong teeeeeeext grooooows and then shriiiinks as you add text to me! ioahsdia soady auydoa aoisyd aosdy ' +
' ' +
this.state.dynamicText}
{'Text limited by height, watch as this reeeeaaaally loooooong teeeeeeext grooooows and then shriiiinks as you add text to me! ioahsdia soady auydoa aoisyd aosdy ' +
' ' +
this.state.dynamicText}
{'Differently sized nested elements will shrink together. '}
{'LARGE TEXT! ' + this.state.dynamicText}
Reset
Remove Text
Add Text
);
}
}
function TextLinkifyExample(props: {}): React.Node {
return (
<>
Phone number: 123-123-1234
Link: https://www.facebook.com
Email: employee@facebook.com
Phone number: 123-123-1234 Link: https://www.facebook.com Email:
employee@facebook.com
Phone number: 123-123-1234 Link: https://www.facebook.com Email:
employee@facebook.com
>
);
}
function TextTransformExample(props: {}): React.Node {
return (
<>
This text should be uppercased.
This TEXT SHOULD be lowercased.
This text should be CAPITALIZED.
Capitalize a date:
the 9th of november, 1998
Capitalize a 2 digit date:
the 25th of december
Mixed:{' '}
uppercase{' '}
LoWeRcAsE{' '}
capitalize each word
Should be "ABC":
abc
Should be "AbC":
abc
{
'.aa\tbb\t\tcc dd EE \r\nZZ I like to eat apples. \n中文éé 我喜欢吃苹果。awdawd '
}
{
'.aa\tbb\t\tcc dd EE \r\nZZ I like to eat apples. \n中文éé 我喜欢吃苹果。awdawd '
}
{
'.aa\tbb\t\tcc dd EE \r\nZZ I like to eat apples. \n中文éé 我喜欢吃苹果。awdawd '
}
{
'.aa\tbb\t\tcc dd EE \r\nZZ I like to eat apples. \n中文éé 我喜欢吃苹果。awdawd '
}
Works with other text styles
>
);
}
function IncludeFontPaddingExample(props: {}): React.Node {
return (
<>
Ey
Default
Ey
includeFontPadding: false
By default Android will put extra space above text to allow for
upper-case accents or other ascenders. With some fonts, this can make
text look slightly misaligned when centered vertically.
>
);
}
function FontVariantsExample(props: {}): React.Node {
return (
<>
Small Caps{'\n'}
Old Style nums 0123456789{'\n'}
Lining nums 0123456789{'\n'}
Tabular nums{'\n'}
1111{'\n'}
2222{'\n'}
Proportional nums{'\n'}
1111{'\n'}
2222{'\n'}
>
);
}
function EllipsizeModeExample(props: {}): React.Node {
return (
<>
This very long text should be truncated with dots in the end.
RNTesterText very long text should be truncated with dots in the middle.
This very long text should be truncated with dots in the beginning.
This very long text should be clipped and this will not be visible.
>
);
}
function FontFamilyExample(props: {}): React.Node {
return (
<>
Sans-Serif
Sans-Serif Bold
Serif
Serif Bold
Monospace
Monospace Bold (After 5.0)
Unknown Font Family
>
);
}
function TextShadowExample(props: {}): React.Node {
return (
<>
Demo text shadow
>
);
}
function AllowFontScalingExample(props: {}): React.Node {
return (
<>
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.
You can disable scaling for your Text component by passing {'"'}
allowFontScaling={'{'}false{'}"'} prop.
This text will not scale.{' '}
This text also won't scale because it inherits "allowFontScaling" from
its parent.
>
);
}
function MaxFontSizeMultiplierExample(props: {}): React.Node {
return (
When allowFontScaling is enabled, you can use the maxFontSizeMultiplier
prop to set an upper limit on how much the font size will be scaled.
This text will not scale up (max 1x)
This text will scale up (max 1.5x)
Inherit max (max 1x)
Override inherited max (max 1.5x)
Ignore inherited max (no max)
);
}
function NumberOfLinesExample(props: {}): React.Node {
return (
Maximum of one line no matter now much I write here. If I keep writing
it{"'"}ll just truncate after one line
Maximum of one line no matter now much I write here. If I keep writing
it{"'"}ll just truncate after one line
RNTesterText of two lines no matter now much I write here. If I keep
writing it{"'"}ll just truncate after two lines
The hotdog should be truncated. The hotdog should be truncated. The
hotdog should be truncated. The hotdog should be truncated. The hotdog
should be truncated. The hotdog should be truncated. The hotdog should
be truncated. The hotdog should be truncated. The hotdog should be
truncated. The hotdog should be truncated.
No maximum lines specified no matter now much I write here. If I keep
writing it{"'"}ll just keep going and going
);
}
function HyphenationExample(props: {}): React.Node {
return (
<>
Normal:
WillHaveAHyphenWhenBreakingForNewLine
None:
WillNotHaveAHyphenWhenBreakingForNewLine
Full:
WillHaveAHyphenWhenBreakingForNewLine
>
);
}
function FontWeightExample(props: {}): React.Node {
return (
<>
Move fast and be bold
Move fast and be normal
FONT WEIGHT 900
FONT WEIGHT 800
FONT WEIGHT 700
FONT WEIGHT 600
FONT WEIGHT 500
FONT WEIGHT 400
FONT WEIGHT 300
FONT WEIGHT 200
FONT WEIGHT 100
FONT WEIGHT 900
FONT WEIGHT 800
FONT WEIGHT 700
FONT WEIGHT 600
FONT WEIGHT 500
FONT WEIGHT 400
FONT WEIGHT 300
FONT WEIGHT 200
FONT WEIGHT 100
>
);
}
function BackgroundColorExample(props: {}): React.Node {
return (
<>
Red background,
{' '}
blue background,
{' '}
inherited blue background,
{' '}
nested green background.
Same alpha as background,
Inherited alpha from background,
Reapply alpha
>
);
}
function ContainerBackgroundColorExample(props: {}): React.Node {
return (
<>
Default containerBackgroundColor (inherited) + backgroundColor wash
{"containerBackgroundColor: 'transparent' + backgroundColor wash"}
>
);
}
function TextDecorationExample(props: {}): React.Node {
return (
<>
Solid underline
None textDecoration
Solid line-through
Both underline and line-through
Mixed text with{' '}
underline
{' '}
and{' '}
line-through
{' '}
text nodes
>
);
}
function NestedExample(props: {}): React.Node {
return (
<>
console.log('1st')}>
(Normal text,
(R)red
(G)green
(B)blue
(C)cyan
(M)magenta
(Y)yellow
(K)black
console.log('2nd')}>
(and bold
console.log('3rd')}>
(and tiny bold italic blue
console.log('4th')}>
(and tiny normal blue)
)
)
)
console.log('1st')}>
(Serif
console.log('2nd')}>
(Serif Bold Italic
console.log('3rd')}>
(Monospace Normal
console.log('4th')}>
(Sans-Serif Bold
console.log('5th')}>
(and Sans-Serif Normal)
)
)
)
)
Entity Name
Nested text with size 8,{' '}
size 23,
and size 8 again
Nested text with red color,{' '}
blue color,
and red color again
(opacity
(is inherited
(and accumulated
(and also applies to the background)
)
)
)
>
);
}
function TextAlignExample(props: {}): React.Node {
return (
auto (default) - english LTR
أحب اللغة العربية auto (default) - arabic RTL
left left left left left left left left left left left left left left
left
center center center center center center center center center center
center
right right right right right right right right right right right right
right
justify (works when api level >= 26 otherwise fallbacks to "left"): this
text component{"'"}s contents are laid out with "textAlign: justify" and
as you can see all of the lines except the last one span the available
width of the parent container.
);
}
function UnicodeExample(props: {}): React.Node {
return (
<>
星际争霸是世界上最好的游戏。
星际争霸是世界上最好的游戏。
星际争霸是世界上最好的游戏。
星际争霸是世界上最好的游戏。星际争霸是世界上最好的游戏。星际争霸是世界上最好的游戏。星际争霸是世界上最好的游戏。
>
);
}
function AndroidMaterialDesignFonts(props: {}): React.Node {
return (
<>
Roboto Regular
Roboto Italic
Roboto Bold
Roboto Bold Italic
Roboto Light
Roboto Light Italic
Roboto Thin (After 4.2)
Roboto Thin Italic (After 4.2)
Roboto Condensed
Roboto Condensed Italic
Roboto Condensed Bold
Roboto Condensed Bold Italic
Roboto Medium (After 5.0)
Roboto Medium Italic (After 5.0)
>
);
}
function CustomFontsExample(props: {}): React.Node {
return (
<>
NotoSerif Regular
NotoSerif Bold Italic
NotoSerif Italic (Missing Font file)
Rubik Regular
Rubik Light
Rubik Bold
Rubik Medium
Rubik Medium Italic
>
);
}
function LineHeightExample(props: {}): React.Node {
return (
<>
Holisticly formulate inexpensive ideas before best-of-breed benefits.{' '}
Continually expedite
magnetic potentialities rather than client-focused interfaces.
Holisticly formulate inexpensive ideas before best-of-breed benefits.{' '}
Continually expedite
magnetic potentialities rather than client-focused interfaces.
Holisticly formulate
Holisticly formulate
>
);
}
function LetterSpacingExample(props: {}): React.Node {
return (
<>
letterSpacing = 0
letterSpacing = 2
letterSpacing = 9
With size and background color
letterSpacing = -1
[letterSpacing = 3]
[Nested letterSpacing = 0]
[Nested letterSpacing = 6]
>
);
}
function TextBaseLineLayoutExample(props: {}): React.Node {
const texts = [];
for (let i = 9; i >= 0; i--) {
texts.push(
{i}
,
);
}
const marker = (
);
const subtitleStyle = {fontSize: 16, marginTop: 8, fontWeight: 'bold'};
return (
{/* $FlowFixMe[incompatible-type] Natural Inference rollout. See
* https://fburl.com/workplace/6291gfvu */}
{'Nested s:'}
{marker}
{texts}
{marker}
{/* $FlowFixMe[incompatible-type] Natural Inference rollout. See
* https://fburl.com/workplace/6291gfvu */}
{'Array of s in :'}
{marker}
{texts}
{marker}
{/* $FlowFixMe[incompatible-type] Natural Inference rollout. See
* https://fburl.com/workplace/6291gfvu */}
{'Interleaving and :'}
{marker}
Some text.
{marker}
Text inside View.
{marker}
{marker}
{/* $FlowFixMe[incompatible-type] Natural Inference rollout. See
* https://fburl.com/workplace/6291gfvu */}
{'Multi-line interleaved and :'}
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris
venenatis,{' '}
mauris eu commodo maximus
{' '}
, ante arcu vestibulum ligula, et scelerisque diam.
{/* $FlowFixMe[incompatible-type] Natural Inference rollout. See
* https://fburl.com/workplace/6291gfvu */}
{'Multi-line alignment'}
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.
{/* $FlowFixMe[incompatible-type] Natural Inference rollout. See
* https://fburl.com/workplace/6291gfvu */}
{':'}
{marker}
{texts}
{marker}
{/* $FlowFixMe[incompatible-type] Natural Inference rollout. See
* https://fburl.com/workplace/6291gfvu */}
{':'}
{marker}
{texts}
{marker}
);
}
const examples = [
{
title: 'Background Color and Border Width',
name: 'background-border-width',
render(): React.Node {
return (
Text with background color only
Text with background color and uniform borderRadii
Text with background color and non-uniform borders
Text with borderWidth
Text with background AND borderWidth
);
},
},
{
title: 'Dynamic Font Size Adjustment',
name: 'ajustingFontSize',
render(): React.Node {
return ;
},
},
{
title: 'Font Size Adjustment with Dynamic Layout',
name: 'textAdjustsDynamicLayout',
render(): React.Node {
return ;
},
},
{
title: 'Wrap',
name: 'wrap',
render(): React.Node {
return (
The text should wrap if it goes on multiple lines. See, this is going
to the next line.
);
},
},
{
title: 'Hyphenation',
name: 'hyphenation',
render(): React.Node {
return ;
},
},
{
title: 'Padding',
name: 'padding',
render(): React.Node {
return (
This text is indented by 10px padding on all sides.
);
},
},
{
title: 'Text metrics legend',
name: 'textMetricLegend',
render(): React.Node {
return ;
},
},
{
title: 'Font Family',
name: 'fontFamily',
render(): React.Node {
return ;
},
},
{
title: 'Android Material Design Fonts',
name: 'androidMaterialDesignFonts',
render(): React.Node {
return ;
},
},
{
title: 'Custom Fonts',
name: 'customFonts',
render(): React.Node {
return ;
},
},
{
title: 'Font Size',
name: 'fontSize',
render(): React.Node {
return (
<>
Size 23
Size 8
>
);
},
},
{
title: 'Color',
name: 'color',
render(): React.Node {
return (
<>
Red color
Blue color
>
);
},
},
{
title: 'Font Weight',
name: 'fontWeight',
render(): React.Node {
return ;
},
},
{
title: 'Font Style',
name: 'fontStyle',
render(): React.Node {
return (
<>
Move fast and be italic
Move fast and be normal
>
);
},
},
{
title: 'Font Style and Weight',
name: 'fontStyleAndWeight',
render(): React.Node {
return (
Move fast and be both bold and italic
);
},
},
{
title: 'Text Decoration',
name: 'textDecoration',
render(): React.Node {
return ;
},
},
{
title: 'Nested',
name: 'nested',
render(): React.Node {
return ;
},
},
{
title: 'Text Align',
name: 'textAlign',
render(): React.Node {
return ;
},
},
{
title: 'Unicode',
name: 'unicode',
render(): React.Node {
return ;
},
},
{
title: 'Spaces',
name: 'spaces',
render(): React.Node {
return (
A {'generated'} {'string'} and some spaces
);
},
},
{
title: 'Line Height',
name: 'lineHeight',
render(): React.Node {
return ;
},
},
{
title: 'Letter Spacing',
name: 'letterSpacing',
render(): React.Node {
return ;
},
},
{
title: 'Toggling Attributes',
name: 'togglingAttributes',
render: AttributeToggler,
},
{
title: 'backgroundColor attribute',
name: 'backgroundColorAttribute',
render(): React.Node {
return ;
},
},
{
title: 'containerBackgroundColor attribute',
name: 'containerBackgroundColorAttribute',
render(): React.Node {
return ;
},
},
{
title: 'numberOfLines attribute',
name: 'numberOfLines',
render(): React.Node {
return ;
},
},
{
title: 'allowFontScaling attribute',
name: 'allowFontScaling',
render(): React.Node {
return ;
},
},
{
title: 'maxFontSizeMultiplier attribute',
name: 'maxFontSizeMultiplier',
render(): React.Node {
return ;
},
},
{
title: 'selectable attribute',
name: 'selectable',
render(): React.Node {
return (
This text is selectable if you click-and-hold, and will offer the
native Android selection menus.
);
},
},
{
title: 'selectionColor attribute',
name: 'selectionColor',
render(): React.Node {
return (
This text will have a orange highlight on selection.
);
},
},
{
title: 'Inline views',
name: 'inlineViewsBasic',
render(): React.Node {
return ;
},
},
{
title: 'Inline views with multiple nested texts',
name: 'inlineViewsMultiple',
render(): React.Node {
return ;
},
},
{
title: 'Inline image/view clipped by ',
name: 'inlineViewsClipped',
render(): React.Node {
return ;
},
},
{
title: 'Relayout inline image',
name: 'relayoutInlineImage',
render(): React.Node {
return ;
},
},
{
title: 'Relayout inline view',
name: 'relayoutInlineView',
render(): React.Node {
return ;
},
},
{
title: 'Relayout nested inline view',
name: 'relayoutNestedInlineView',
render(): React.Node {
return ;
},
},
{
title: 'Text shadow',
name: 'textShadow',
render(): React.Node {
return ;
},
},
{
title: 'Ellipsize mode',
name: 'ellipsizeMode',
render(): React.Node {
return ;
},
},
{
title: 'Font variants',
name: 'fontVariants',
render(): React.Node {
return ;
},
},
{
title: 'Include Font Padding',
name: 'includeFontPadding',
render(): React.Node {
return ;
},
},
{
title: 'Text Transform',
name: 'textTransform',
render(): React.Node {
return ;
},
},
{
title: 'Substring Emoji (should only see "test")',
name: 'substringEmoji',
render(): React.Node {
return {'test🙃'.substring(0, 5)};
},
},
{
title: 'Text linkify',
name: 'textLinkify',
render(): React.Node {
return ;
},
},
{
title: "Text `alignItems: 'baseline'` style",
name: 'alignItemsBaseline',
render(): React.Node {
return ;
},
},
{
title: 'Selectable Text',
name: 'selectableText',
render(): React.Node {
return (
Text element is selectable
);
},
},
{
title: 'Text alignment',
name: 'textAlignment',
render(): React.Node {
return (
Text element aligned to the top via textAlignVertical
Text element aligned to the top via verticalAlign
Text element aligned to the middle via textAlignVertical
Text element aligned to the middle via verticalAlign
);
},
},
{
title: 'Clipping',
name: 'clipping',
render: function (): React.Node {
return (
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.
);
},
},
{
title: 'Box Shadow',
name: 'boxShadow',
render: function (): React.Node {
return (
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.
);
},
},
{
title: 'Disabled',
name: 'disabled',
render: function (): React.Node {
return (
This text has its corresponding text view in the disabled state for
testing purposes.
);
},
},
...TextSharedExamples,
];
const styles = StyleSheet.create({
backgroundColorText: {
left: 5,
backgroundColor: 'rgba(100, 100, 100, 0.3)',
},
includeFontPaddingText: {
fontSize: 120,
fontFamily: 'sans-serif',
backgroundColor: '#EEEEEE',
color: '#000000',
textAlignVertical: 'center',
alignSelf: 'center',
},
wrappedText: {
maxWidth: 300,
},
});
module.exports = ({
title: 'Text',
documentationURL: 'https://reactnative.dev/docs/text',
category: 'Basic',
description: 'Base component for rendering styled text.',
displayName: 'TextExample',
examples,
}: RNTesterModule);