React Native integration for React Navigation providing navigation containers, deep linking, and platform-specific navigation behaviors.
—
React Navigation's theming system provides built-in light and dark themes with full customization support. Themes control colors, fonts, and visual styling across all navigation components.
Pre-configured light and dark themes that follow platform design guidelines.
/** Default light theme following iOS design guidelines */
const DefaultTheme: Theme;
/** Default dark theme following iOS design guidelines */
const DarkTheme: Theme;
interface Theme {
/** Whether this is a dark theme */
dark: boolean;
/** Color palette for navigation components */
colors: {
/** Primary color for active elements */
primary: string;
/** Background color for screens */
background: string;
/** Background color for cards and surfaces */
card: string;
/** Primary text color */
text: string;
/** Border and separator color */
border: string;
/** Color for notifications and badges */
notification: string;
};
/** Font configurations for different text weights */
fonts: {
regular: FontStyle;
medium: FontStyle;
bold: FontStyle;
heavy: FontStyle;
};
}
interface FontStyle {
/** Font family name */
fontFamily: string;
/** Font weight specification */
fontWeight: 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900';
}Usage Examples:
import { NavigationContainer, DefaultTheme, DarkTheme } from '@react-navigation/native';
import { useColorScheme } from 'react-native';
// Automatic theme switching based on device settings
function App() {
const scheme = useColorScheme();
return (
<NavigationContainer theme={scheme === 'dark' ? DarkTheme : DefaultTheme}>
{/* Your navigation structure */}
</NavigationContainer>
);
}
// Always use light theme
function LightApp() {
return (
<NavigationContainer theme={DefaultTheme}>
{/* Your navigation structure */}
</NavigationContainer>
);
}
// Always use dark theme
function DarkApp() {
return (
<NavigationContainer theme={DarkTheme}>
{/* Your navigation structure */}
</NavigationContainer>
);
}Create custom themes by extending or completely replacing the built-in themes.
// Custom theme creation patterns
type CustomTheme = Theme;
// Theme color values for DefaultTheme
const DefaultThemeColors = {
primary: 'rgb(0, 122, 255)',
background: 'rgb(242, 242, 242)',
card: 'rgb(255, 255, 255)',
text: 'rgb(28, 28, 30)',
border: 'rgb(216, 216, 216)',
notification: 'rgb(255, 59, 48)',
};
// Theme color values for DarkTheme
const DarkThemeColors = {
primary: 'rgb(10, 132, 255)',
background: 'rgb(1, 1, 1)',
card: 'rgb(18, 18, 18)',
text: 'rgb(229, 229, 231)',
border: 'rgb(39, 39, 41)',
notification: 'rgb(255, 69, 58)',
};Custom Theme Examples:
// Extend existing theme
const CustomLightTheme = {
...DefaultTheme,
colors: {
...DefaultTheme.colors,
primary: '#007AFF',
notification: '#FF3B30',
},
};
// Brand-specific theme
const BrandTheme = {
...DefaultTheme,
colors: {
...DefaultTheme.colors,
primary: '#6366f1', // Indigo
background: '#f8fafc', // Slate 50
card: '#ffffff',
text: '#0f172a', // Slate 900
border: '#e2e8f0', // Slate 200
notification: '#ef4444', // Red 500
},
};
// Complete custom theme
const FullCustomTheme: Theme = {
dark: false,
colors: {
primary: '#8b5cf6', // Purple
background: '#faf5ff', // Purple 50
card: '#ffffff',
text: '#581c87', // Purple 900
border: '#c4b5fd', // Purple 300
notification: '#f59e0b', // Amber 500
},
fonts: {
regular: {
fontFamily: 'Inter-Regular',
fontWeight: '400',
},
medium: {
fontFamily: 'Inter-Medium',
fontWeight: '500',
},
bold: {
fontFamily: 'Inter-Bold',
fontWeight: '700',
},
heavy: {
fontFamily: 'Inter-Black',
fontWeight: '900',
},
},
};
// Dynamic theme based on user preferences
function AppWithDynamicTheme() {
const [themeMode, setThemeMode] = useState<'light' | 'dark' | 'brand'>('light');
const getTheme = () => {
switch (themeMode) {
case 'dark':
return DarkTheme;
case 'brand':
return BrandTheme;
default:
return DefaultTheme;
}
};
return (
<NavigationContainer theme={getTheme()}>
{/* Your navigation structure */}
</NavigationContainer>
);
}Customize font families and weights for different text elements.
interface FontStyle {
/** Font family name - should match fonts available in your app */
fontFamily: string;
/** CSS-style font weight specification */
fontWeight: 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900';
}
// Default font configuration
const defaultFonts = {
regular: {
fontFamily: 'System',
fontWeight: 'normal' as const,
},
medium: {
fontFamily: 'System',
fontWeight: '500' as const,
},
bold: {
fontFamily: 'System',
fontWeight: '600' as const,
},
heavy: {
fontFamily: 'System',
fontWeight: '700' as const,
},
};Font Customization Examples:
// Custom font theme
const CustomFontTheme = {
...DefaultTheme,
fonts: {
regular: {
fontFamily: 'Roboto-Regular',
fontWeight: '400',
},
medium: {
fontFamily: 'Roboto-Medium',
fontWeight: '500',
},
bold: {
fontFamily: 'Roboto-Bold',
fontWeight: '700',
},
heavy: {
fontFamily: 'Roboto-Black',
fontWeight: '900',
},
},
};
// Mixed font families
const MixedFontTheme = {
...DefaultTheme,
fonts: {
regular: {
fontFamily: 'Inter-Regular',
fontWeight: '400',
},
medium: {
fontFamily: 'Inter-Medium',
fontWeight: '500',
},
bold: {
fontFamily: 'Poppins-SemiBold', // Different font for bold
fontWeight: '600',
},
heavy: {
fontFamily: 'Poppins-Bold',
fontWeight: '700',
},
},
};
// Platform-specific fonts
const PlatformFontTheme = {
...DefaultTheme,
fonts: {
regular: {
fontFamily: Platform.select({
ios: 'San Francisco',
android: 'Roboto',
default: 'System',
}),
fontWeight: '400',
},
medium: {
fontFamily: Platform.select({
ios: 'San Francisco',
android: 'Roboto',
default: 'System',
}),
fontWeight: '500',
},
bold: {
fontFamily: Platform.select({
ios: 'San Francisco',
android: 'Roboto',
default: 'System',
}),
fontWeight: '600',
},
heavy: {
fontFamily: Platform.select({
ios: 'San Francisco',
android: 'Roboto',
default: 'System',
}),
fontWeight: '700',
},
},
};Access theme values in your components using React Navigation's theming hooks.
// Theme access is provided by @react-navigation/core
import { useTheme } from '@react-navigation/core';
function useTheme(): Theme;Component Usage Examples:
import { useTheme } from '@react-navigation/native';
import { View, Text, StyleSheet } from 'react-native';
// Basic theme usage
function ThemedComponent() {
const { colors, fonts } = useTheme();
return (
<View style={[styles.container, { backgroundColor: colors.card }]}>
<Text style={[fonts.bold, { color: colors.text }]}>
Themed Text
</Text>
</View>
);
}
// Dynamic styling based on theme
function AdaptiveComponent({ children }) {
const { colors, dark } = useTheme();
return (
<View style={[
styles.container,
{
backgroundColor: colors.card,
borderColor: colors.border,
shadowColor: dark ? colors.border : '#000',
shadowOpacity: dark ? 0.3 : 0.1,
}
]}>
{children}
</View>
);
}
// Theme-aware button
function ThemedButton({ title, onPress, variant = 'primary' }) {
const { colors, fonts } = useTheme();
const getButtonStyle = () => {
switch (variant) {
case 'primary':
return {
backgroundColor: colors.primary,
borderColor: colors.primary,
};
case 'secondary':
return {
backgroundColor: 'transparent',
borderColor: colors.border,
};
default:
return {
backgroundColor: colors.card,
borderColor: colors.border,
};
}
};
const getTextStyle = () => {
switch (variant) {
case 'primary':
return { color: '#fff' };
default:
return { color: colors.text };
}
};
return (
<TouchableOpacity
style={[styles.button, getButtonStyle()]}
onPress={onPress}
>
<Text style={[fonts.medium, getTextStyle()]}>
{title}
</Text>
</TouchableOpacity>
);
}
const styles = StyleSheet.create({
container: {
padding: 16,
borderWidth: 1,
borderRadius: 8,
},
button: {
paddingVertical: 12,
paddingHorizontal: 24,
borderRadius: 6,
borderWidth: 1,
alignItems: 'center',
},
});Save and restore user theme preferences across app sessions.
// Theme persistence patterns
interface ThemePreference {
mode: 'light' | 'dark' | 'system';
customColors?: Partial<Theme['colors']>;
}Persistence Examples:
import AsyncStorage from '@react-native-async-storage/async-storage';
// Theme context for app-wide theme management
const ThemeContext = createContext<{
theme: Theme;
themeMode: 'light' | 'dark' | 'system';
setThemeMode: (mode: 'light' | 'dark' | 'system') => void;
}>({
theme: DefaultTheme,
themeMode: 'system',
setThemeMode: () => {},
});
// Theme provider with persistence
function ThemeProvider({ children }) {
const systemColorScheme = useColorScheme();
const [themeMode, setThemeMode] = useState<'light' | 'dark' | 'system'>('system');
// Load saved theme preference
useEffect(() => {
const loadTheme = async () => {
try {
const savedTheme = await AsyncStorage.getItem('theme-mode');
if (savedTheme) {
setThemeMode(savedTheme as 'light' | 'dark' | 'system');
}
} catch (error) {
console.error('Failed to load theme preference:', error);
}
};
loadTheme();
}, []);
// Save theme preference when changed
const handleThemeChange = async (mode: 'light' | 'dark' | 'system') => {
try {
await AsyncStorage.setItem('theme-mode', mode);
setThemeMode(mode);
} catch (error) {
console.error('Failed to save theme preference:', error);
}
};
// Determine active theme
const getActiveTheme = (): Theme => {
switch (themeMode) {
case 'dark':
return DarkTheme;
case 'light':
return DefaultTheme;
case 'system':
return systemColorScheme === 'dark' ? DarkTheme : DefaultTheme;
default:
return DefaultTheme;
}
};
const theme = getActiveTheme();
return (
<ThemeContext.Provider value={{
theme,
themeMode,
setThemeMode: handleThemeChange,
}}>
<NavigationContainer theme={theme}>
{children}
</NavigationContainer>
</ThemeContext.Provider>
);
}
// Theme settings screen
function ThemeSettingsScreen() {
const { themeMode, setThemeMode } = useContext(ThemeContext);
return (
<View>
<Text>Theme Settings</Text>
<Button
title="Light"
onPress={() => setThemeMode('light')}
disabled={themeMode === 'light'}
/>
<Button
title="Dark"
onPress={() => setThemeMode('dark')}
disabled={themeMode === 'dark'}
/>
<Button
title="System"
onPress={() => setThemeMode('system')}
disabled={themeMode === 'system'}
/>
</View>
);
}Install with Tessl CLI
npx tessl i tessl/npm-react-navigation--native