Skip to content

Typography

Typography provides a complete text rendering solution with predefined variants, semantic color options, and consistent styling across your React Native application. It includes specialized components for different text hierarchies and use cases.

import {
Typography,
H1, H2, H3, H4, H5, H6,
P, Heading, Title, Subtitle, Body, Small,
Display, Lead, Caption, Overline, Label, Code, Quote,
TextPrimary, TextSecondary, TextError, TextSuccess, TextWarning, TextInfo
} from 'rnc-theme';
<Typography variant="body">
This is basic body text with default styling.
</Typography>
PropTypeDefaultDescription
variantTypographyVariant'body'Text style variant
weightTypographyWeight-Font weight override
colorstringtheme.colors.textText color
alignTypographyAlign'left'Text alignment
numberOfLinesnumber-Maximum lines to display
ellipsizeMode'head' | 'middle' | 'tail' | 'clip'-Text truncation mode
selectablebooleanfalseAllow text selection
onPress() => void-Press handler function
styleStyleProp<TextStyle>-Additional text styles
VariantFont SizeLine HeightWeightUse Case
display48px56px800Hero titles, marketing headers
h132px40px700Page titles, main headings
h228px36px700Section headings
h324px32px600Subsection titles
h420px28px600Component titles
h518px24px500Card headers, labels
h616px22px500Small headings
headingTheme-basedTheme-based700Generic heading
titleTheme-basedTheme-based600Content titles
subtitleTheme-basedTheme-based500Content subtitles
lead20px30px400Lead paragraphs, introductions
bodyTheme-basedTheme-based400Regular body text
smallTheme-basedTheme-based400Small text, metadata
caption12px16px400Image captions, footnotes
overline10px14px600Category labels, tags
button14px20px600Button text
label12px16px500Form labels
code14px20px400Code snippets, monospace
quote18px28px400Blockquotes, testimonials
ValueDescription
leftLeft-aligned text (default)
centerCenter-aligned text
rightRight-aligned text
justifyJustified text alignment
<VStack spacing="lg">
<Display>Hero Display Text</Display>
<H1>Page Title</H1>
<H2>Section Heading</H2>
<H3>Subsection Title</H3>
<H4>Component Header</H4>
<H5>Card Title</H5>
<H6>Small Heading</H6>
<Heading>Generic Heading</Heading>
<Title>Content Title</Title>
<Subtitle>Content Subtitle</Subtitle>
</VStack>
<VStack spacing="md">
<Lead>
This is a lead paragraph that introduces the main content
with larger, more prominent text styling.
</Lead>
<P>
Regular paragraph text for body content. This component
uses the body variant by default and is perfect for
main content areas.
</P>
<Small>
Small text for metadata, timestamps, or secondary information
that should be less prominent than body text.
</Small>
<Caption>Image caption or footnote text</Caption>
</VStack>
<VStack spacing="md">
<Overline>CATEGORY LABEL</Overline>
<Label>Form Field Label</Label>
<Code>const greeting = 'Hello World';</Code>
<Quote>
"This is a beautifully styled quote that stands out
from regular body text with italic styling."
</Quote>
</VStack>
<VStack spacing="sm">
<TextPrimary variant="h3">Primary Heading</TextPrimary>
<TextSecondary variant="body">Secondary information text</TextSecondary>
<TextSuccess variant="small">✓ Operation completed successfully</TextSuccess>
<TextError variant="small">✗ An error occurred</TextError>
<TextWarning variant="small">⚠ Warning message</TextWarning>
<TextInfo variant="small">ℹ Information notice</TextInfo>
</VStack>
const ArticleContent = ({ article }) => {
return (
<ScrollView padding="xl">
<VStack spacing="lg">
{/* Article Header */}
<VStack spacing="md">
<Overline>{article.category.toUpperCase()}</Overline>
<H1>{article.title}</H1>
<TextSecondary variant="body">
By {article.author}{article.publishDate}
</TextSecondary>
</VStack>
{/* Lead Paragraph */}
<Lead>{article.excerpt}</Lead>
{/* Article Content */}
<VStack spacing="md">
{article.sections.map((section, index) => (
<VStack key={index} spacing="sm">
<H2>{section.title}</H2>
{section.paragraphs.map((paragraph, pIndex) => (
<P key={pIndex}>{paragraph}</P>
))}
</VStack>
))}
</VStack>
{/* Quote */}
{article.quote && (
<Quote>"{article.quote.text}"</Quote>
)}
{/* Article Footer */}
<VStack spacing="sm">
<Small>Last updated: {article.lastUpdated}</Small>
<TextSecondary variant="caption">
#{article.tags.join(' #')}
</TextSecondary>
</VStack>
</VStack>
</ScrollView>
);
};
const ProfileCard = ({ user }) => {
return (
<Card padding="lg">
<VStack spacing="md" align="center">
<Avatar size="xl" source={{ uri: user.avatar }} />
<VStack spacing="sm" align="center">
<H3>{user.name}</H3>
<TextSecondary variant="body">{user.title}</TextSecondary>
<Caption>{user.location}</Caption>
</VStack>
<HStack spacing="xl" justify="center">
<VStack align="center">
<H4>{user.followers}</H4>
<Label>Followers</Label>
</VStack>
<VStack align="center">
<H4>{user.following}</H4>
<Label>Following</Label>
</VStack>
<VStack align="center">
<H4>{user.posts}</H4>
<Label>Posts</Label>
</VStack>
</HStack>
<P align="center" numberOfLines={3}>
{user.bio}
</P>
</VStack>
</Card>
);
};
const ContactForm = () => {
const [form, setForm] = useState({
name: '',
email: '',
message: ''
});
return (
<VStack spacing="lg" padding="xl">
<VStack spacing="sm">
<H2>Contact Us</H2>
<TextSecondary variant="body">
We'd love to hear from you. Send us a message and we'll respond as soon as possible.
</TextSecondary>
</VStack>
<VStack spacing="md">
<VStack spacing="xs">
<Label>Full Name</Label>
<TextInput
value={form.name}
onChangeText={(text) => setForm(prev => ({ ...prev, name: text }))}
placeholder="Enter your full name"
/>
</VStack>
<VStack spacing="xs">
<Label>Email Address</Label>
<TextInput
value={form.email}
onChangeText={(text) => setForm(prev => ({ ...prev, email: text }))}
placeholder="Enter your email"
keyboardType="email-address"
/>
</VStack>
<VStack spacing="xs">
<Label>Message</Label>
<TextInput
value={form.message}
onChangeText={(text) => setForm(prev => ({ ...prev, message: text }))}
placeholder="Enter your message"
multiline
numberOfLines={4}
/>
<Caption>Minimum 10 characters required</Caption>
</VStack>
</VStack>
<Button variant="primary" fullWidth>
<ButtonText>Send Message</ButtonText>
</Button>
</VStack>
);
};
const CodeExample = () => {
return (
<VStack spacing="md" padding="lg">
<H3>API Usage Example</H3>
<P>
Here's how to implement the authentication hook in your component:
</P>
<Card padding="md" backgroundColor="codeBackground">
<Code>
{`import { useAuth } from './hooks/useAuth';
const LoginScreen = () => {
const { login, loading, error } = useAuth();
return (
<View>
{/* Login form implementation */}
</View>
);
};`}
</Code>
</Card>
<VStack spacing="sm">
<H4>Parameters</H4>
<P>The hook accepts the following configuration:</P>
<VStack spacing="xs">
<HStack>
<Code>redirectUrl</Code>
<Small> - Optional redirect after login</Small>
</HStack>
<HStack>
<Code>persistToken</Code>
<Small> - Whether to persist authentication</Small>
</HStack>
</VStack>
</VStack>
</VStack>
);
};
const StatCard = ({ title, value, change, trend }) => {
return (
<Card padding="lg">
<VStack spacing="sm">
<Label>{title.toUpperCase()}</Label>
<H2>{value}</H2>
<HStack spacing="xs" align="center">
{trend === 'up' ? (
<TextSuccess variant="small">{change}%</TextSuccess>
) : (
<TextError variant="small">{change}%</TextError>
)}
<Small>vs last month</Small>
</HStack>
</VStack>
</Card>
);
};
const Dashboard = ({ stats }) => {
return (
<VStack spacing="xl" padding="xl">
<VStack spacing="sm">
<H1>Dashboard</H1>
<TextSecondary variant="body">
Welcome back! Here's what's happening with your account.
</TextSecondary>
</VStack>
<Grid columns={2} spacing="md">
{stats.map((stat, index) => (
<StatCard key={index} {...stat} />
))}
</Grid>
</VStack>
);
};
const CustomTypography = () => {
return (
<VStack spacing="md">
<Typography variant="h2" weight="300">Light Heading</Typography>
<Typography variant="h2" weight="400">Regular Heading</Typography>
<Typography variant="h2" weight="500">Medium Heading</Typography>
<Typography variant="h2" weight="600">Semibold Heading</Typography>
<Typography variant="h2" weight="700">Bold Heading</Typography>
<Typography variant="h2" weight="800">Extra Bold Heading</Typography>
</VStack>
);
};
const TruncatedText = ({ longText }) => {
return (
<VStack spacing="md" padding="lg">
<Typography
variant="body"
numberOfLines={1}
ellipsizeMode="tail"
>
{longText}
</Typography>
<Typography
variant="body"
numberOfLines={2}
ellipsizeMode="middle"
>
{longText}
</Typography>
<Typography
variant="body"
numberOfLines={3}
ellipsizeMode="head"
>
{longText}
</Typography>
</VStack>
);
};
const InteractiveText = () => {
const handlePress = () => {
console.log('Text pressed!');
};
return (
<VStack spacing="md">
<Typography
variant="body"
color="#007AFF"
onPress={handlePress}
selectable={false}
>
Tap this text to trigger an action
</Typography>
<Typography
variant="body"
selectable={true}
>
This text can be selected and copied
</Typography>
</VStack>
);
};
<VStack spacing="lg" align="center" padding="xl">
<Display align="center">
Build Amazing Apps
</Display>
<Lead align="center">
Create beautiful, performant React Native applications
with our comprehensive design system.
</Lead>
<Button variant="primary" size="lg">
<ButtonText>Get Started</ButtonText>
</Button>
</VStack>

Hierarchy & Contrast

  • Use heading variants (H1-H6) to establish clear visual hierarchy
  • Ensure sufficient color contrast between text and background
  • Limit the number of different text sizes on a single screen

Readability

  • Use appropriate line heights for better readability
  • Consider text truncation for dynamic content that may overflow
  • Test text rendering across different device sizes and orientations

Performance

  • Use React.memo for frequently updated text components
  • Avoid inline styles that create new objects on each render
  • Consider using numberOfLines for long content that might cause performance issues