Typography
Typography renders text with the type scale of the theme, semantic colors and automatic light and dark mode. Use it instead of a bare React Native Text so every piece of text follows the theme. Copy it as described in the introduction, together with core.
Basic
Without props, the text uses the body1 variant and the primary text color.
import { StyleSheet, View } from 'react-native';
import { Typography } from 'tessera';
export function BasicExample() {
return (
<View style={styles.container}>
<Typography variant="h4">Heading</Typography>
<Typography>
Without a variant, Typography renders the body1 style of the theme.
</Typography>
</View>
);
}
const styles = StyleSheet.create({
container: {
gap: 8,
},
});
Heading
Heading
Variants
variant picks a token from the type scale: h1 to h6, subtitle1, subtitle2, body1, body2, button, caption and overline.
import { StyleSheet, View } from 'react-native';
import { Typography } from 'tessera';
import type { TypographyVariant } from 'tessera';
const variants: TypographyVariant[] = [
'h1',
'h2',
'h3',
'h4',
'h5',
'h6',
'subtitle1',
'subtitle2',
'body1',
'body2',
'button',
'caption',
'overline',
];
export function VariantsExample() {
return (
<View style={styles.container}>
{variants.map(variant => (
<View key={variant} style={styles.row}>
<Typography variant="caption" color="secondary">
{variant}
</Typography>
<Typography variant={variant}>The quick brown fox</Typography>
</View>
))}
</View>
);
}
const styles = StyleSheet.create({
container: {
gap: 12,
},
row: {
gap: 4,
},
});
The quick brown fox
The quick brown fox
The quick brown fox
The quick brown fox
The quick brown fox
The quick brown fox
The quick brown fox
The quick brown fox
The quick brown fox
The quick brown fox
The quick brown fox
The quick brown fox
Tones
color sets the text color from the palette. Each value resolves to the text variant of its color, the one that meets WCAG AA on the background.
import { StyleSheet, View } from 'react-native';
import { Typography } from 'tessera';
import type { TypographyColor } from 'tessera';
const tones: TypographyColor[] = [
'primary',
'secondary',
'success',
'info',
'warning',
'error',
'disabled',
];
export function TonesExample() {
return (
<View style={styles.container}>
{tones.map(tone => (
<Typography key={tone} color={tone}>
{tone}: sample text
</Typography>
))}
</View>
);
}
const styles = StyleSheet.create({
container: {
gap: 8,
},
});
Weight
weight overrides the font weight of the variant. Size and line height do not change.
import { StyleSheet, View } from 'react-native';
import { Typography } from 'tessera';
export function WeightExample() {
return (
<View style={styles.container}>
<Typography variant="h4" weight="400">
Heading with regular weight
</Typography>
<Typography weight="700">Body text with bold weight</Typography>
<Typography variant="body2" weight="500">
Body 2 with medium weight
</Typography>
</View>
);
}
const styles = StyleSheet.create({
container: {
gap: 8,
},
});
Heading with regular weight
Heading with regular weight
Style override
style is applied last, after the variant, weight, color and alignment. It accepts a React Native style or a function that receives the theme.
import { StyleSheet, View } from 'react-native';
import { Typography } from 'tessera';
export function StyleOverrideExample() {
return (
<View style={styles.container}>
<Typography style={styles.spaced}>
Object style adds letter spacing and a top margin.
</Typography>
<Typography
style={theme => ({
textDecorationLine: 'underline',
textDecorationColor: theme.palette.primary.textColor,
})}>
Function style reads the theme to underline with the primary color.
</Typography>
</View>
);
}
const styles = StyleSheet.create({
container: {
gap: 8,
},
spaced: {
letterSpacing: 2,
marginTop: 4,
},
});
Accessibility
What the component sets:
h1toh6haveaccessibilityRole="header", so screen readers announce them as headings. Pass your ownaccessibilityRoleto replace it.maxFontSizeMultiplierdefaults to2, which limits how much the system font size scales the text.- The component is not interactive. It does not capture focus or announce anything by itself.
What you must provide:
- Meaningful content. Avoid purely decorative text inside touchable rows.
- A non-heading variant, such as
body1, for text that repeats in lists.
Dependencies
| Import | Reason |
|---|---|
react-native (Text, types) | Primitive that the component wraps |
core (resolveTesseraStyle, useTheme, types) | Theme tokens and the style escape hatch |
Files
Copy core/ once for the whole catalog, then this component's folder:
core/ # all files, copied once
components/typography/index.ts
components/typography/typography.tsx
Version and changes
Changes to this component are listed in CHANGELOG.md. Each entry for this component starts with the typography scope.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
variant | TypographyVariant | 'body1' | Token from the type scale. h1 to h6 are announced as headings. |
weight | TypographyToken['fontWeight'] | — | Overrides the font weight of the variant. |
color | TypographyColor | text.primary | primary, secondary, success, info, warning, error, disabled. caption and overline use their own muted color when omitted. |
align | TextStyle['textAlign'] | — | left, center, right, justify. |
style | TesseraStyleProp<TextStyle> | — | React Native style, or (theme) => style. Applied last. |
maxFontSizeMultiplier | number | 2 | Upper limit for the system font scaling. |
Any other Text prop, such as accessibilityLabel or numberOfLines, is passed to the underlying Text unchanged.