Skip to content

Commit 797af4d

Browse files
committed
chore(demo): add custom AppHeader component
1 parent 9717a54 commit 797af4d

2 files changed

Lines changed: 91 additions & 4 deletions

File tree

examples/demo/App.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { SafeAreaProvider } from 'react-native-safe-area-context';
66
import Toast from 'react-native-toast-message';
77

88
import OneSignalLogo from './assets/onesignal_logo.svg';
9+
import AppHeader from './src/components/AppHeader';
910
import { OneSignalProvider } from './src/hooks/useOneSignal';
1011
import HomeScreen from './src/screens/HomeScreen';
1112
import SecondaryScreen from './src/screens/SecondaryScreen';
@@ -26,10 +27,7 @@ function App() {
2627
<NavigationContainer>
2728
<Stack.Navigator
2829
screenOptions={{
29-
headerStyle: { backgroundColor: AppColors.osPrimary },
30-
headerTintColor: AppColors.white,
31-
headerTitleAlign: 'center',
32-
headerShadowVisible: false,
30+
header: (props) => <AppHeader {...props} />,
3331
}}
3432
>
3533
<Stack.Screen
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import { useNavigation } from '@react-navigation/native';
2+
import type { NativeStackHeaderProps } from '@react-navigation/native-stack';
3+
import React from 'react';
4+
import { Platform, Pressable, StyleSheet, Text, View } from 'react-native';
5+
import { useSafeAreaInsets } from 'react-native-safe-area-context';
6+
import Icon from 'react-native-vector-icons/MaterialIcons';
7+
8+
import { AppColors } from '../theme';
9+
10+
export default function AppHeader({ options, back }: NativeStackHeaderProps) {
11+
const navigation = useNavigation();
12+
const insets = useSafeAreaInsets();
13+
14+
const titleNode =
15+
typeof options.headerTitle === 'function' ? (
16+
options.headerTitle({ children: options.title ?? '', tintColor: AppColors.white })
17+
) : (
18+
<Text style={styles.title}>{options.title ?? ''}</Text>
19+
);
20+
21+
return (
22+
<View style={[styles.shadowWrap, { paddingTop: insets.top }]}>
23+
<View style={styles.bar}>
24+
<View style={styles.side}>
25+
{back ? (
26+
<Pressable
27+
onPress={navigation.goBack}
28+
hitSlop={12}
29+
style={({ pressed }) => [styles.backBtn, pressed && styles.pressed]}
30+
>
31+
<Icon name="arrow-back" size={24} color={AppColors.white} />
32+
</Pressable>
33+
) : null}
34+
</View>
35+
<View style={styles.center}>{titleNode}</View>
36+
<View style={styles.side} />
37+
</View>
38+
</View>
39+
);
40+
}
41+
42+
const styles = StyleSheet.create({
43+
shadowWrap: {
44+
backgroundColor: AppColors.osPrimary,
45+
...Platform.select({
46+
ios: {
47+
shadowColor: '#000',
48+
shadowOffset: { width: 0, height: 4 },
49+
shadowOpacity: 0.25,
50+
shadowRadius: 6,
51+
},
52+
android: {
53+
elevation: 8,
54+
},
55+
}),
56+
zIndex: 10,
57+
},
58+
bar: {
59+
height: 56,
60+
flexDirection: 'row',
61+
alignItems: 'center',
62+
paddingHorizontal: 4,
63+
},
64+
side: {
65+
width: 56,
66+
alignItems: 'center',
67+
justifyContent: 'center',
68+
},
69+
center: {
70+
flex: 1,
71+
alignItems: 'center',
72+
justifyContent: 'center',
73+
},
74+
backBtn: {
75+
width: 40,
76+
height: 40,
77+
alignItems: 'center',
78+
justifyContent: 'center',
79+
borderRadius: 20,
80+
},
81+
pressed: {
82+
opacity: 0.6,
83+
},
84+
title: {
85+
color: AppColors.white,
86+
fontSize: 18,
87+
fontWeight: '600',
88+
},
89+
});

0 commit comments

Comments
 (0)