diff --git a/src/cli.ts b/src/cli.ts
index 4d53a25..ccb38a4 100644
--- a/src/cli.ts
+++ b/src/cli.ts
@@ -45,11 +45,6 @@ export default function runCli() {
.description('Install and configure Jest and Testing Library')
.action(buildAction(import('./commands/testingLibrary')));
- program
- .command('navigation')
- .description('Install and configure React Navigation')
- .action(buildAction(import('./commands/navigation')));
-
printWelcome();
program.parse();
}
diff --git a/src/commands/__tests__/navigation.test.ts b/src/commands/__tests__/navigation.test.ts
deleted file mode 100644
index f2715e7..0000000
--- a/src/commands/__tests__/navigation.test.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import { vol } from 'memfs';
-import { expect, test, vi } from 'vitest';
-import addDependency from '../../util/addDependency';
-import copyTemplateDirectory from '../../util/copyTemplateDirectory';
-import addNavigation from '../navigation';
-
-vi.mock('../../util/addDependency');
-vi.mock('../../util/copyTemplateDirectory');
-
-test('installs React Navigation', async () => {
- vol.fromJSON({
- 'package.json': JSON.stringify({
- scripts: {},
- dependencies: {
- expo: '1.0.0',
- },
- devDependencies: {},
- }),
- 'yarn.lock': '',
- });
-
- await addNavigation();
-
- expect(addDependency).toHaveBeenCalledWith(
- '@react-navigation/native @react-navigation/native-stack',
- );
- expect(copyTemplateDirectory).toHaveBeenCalledWith({
- templateDir: 'reactNavigation',
- });
-});
diff --git a/src/commands/createApp.ts b/src/commands/createApp.ts
index 5d6afb5..46aae54 100644
--- a/src/commands/createApp.ts
+++ b/src/commands/createApp.ts
@@ -27,7 +27,6 @@ export async function createApp(
options: Options = {},
) {
const { interactive = true } = options;
-
globals.interactive = interactive;
const appName = await validateAndSanitizeAppName(name);
@@ -38,6 +37,7 @@ export async function createApp(
const spinner = ora('Creating app with Belt').start();
await exec(`mkdir ${appName}`);
+
await copyTemplateDirectory({
templateDir: 'boilerplate',
destinationDir: appName,
@@ -59,7 +59,6 @@ export async function createApp(
spinner.start('Installing dependencies');
const packageManager = getPackageManager(options);
await exec(`${packageManager} install`);
-
await exec('git init');
await commit('Initial commit');
spinner.succeed('Installed dependencies');
diff --git a/src/commands/navigation.ts b/src/commands/navigation.ts
deleted file mode 100644
index bf9bd8d..0000000
--- a/src/commands/navigation.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import ora from 'ora';
-import addDependency from '../util/addDependency';
-import copyTemplateDirectory from '../util/copyTemplateDirectory';
-import exec from '../util/exec';
-import isExpo from '../util/isExpo';
-
-export default async function addNavigation() {
- const spinner = ora().start('Installing React Navigation');
- const expo = await isExpo();
-
- if (expo) {
- await exec(
- 'npx expo install react-native-screens react-native-safe-area-context',
- );
- } else {
- await addDependency('react-native-screens react-native-safe-area-context');
- }
-
- await addDependency(
- '@react-navigation/native @react-navigation/native-stack',
- );
-
- await copyTemplateDirectory({
- templateDir: 'reactNavigation',
- });
-
- spinner.succeed(
- 'Successfully installed React Navigation and Native Stack navigator',
- );
-}
diff --git a/templates/boilerplate/jest.setup.js b/templates/boilerplate/jest.setup.js
index e1f30ff..7d448c7 100644
--- a/templates/boilerplate/jest.setup.js
+++ b/templates/boilerplate/jest.setup.js
@@ -7,6 +7,9 @@ beforeEach(() => {
jest.clearAllMocks();
});
+jest.mock('expo-font');
+jest.mock('expo-asset');
+
jest.mock('react-native-safe-area-context', () => mockSafeAreaContext);
jest.mock('react-native/Libraries/Alert/Alert', () => ({
diff --git a/templates/boilerplate/package.json b/templates/boilerplate/package.json
index 40af946..99103ba 100644
--- a/templates/boilerplate/package.json
+++ b/templates/boilerplate/package.json
@@ -18,7 +18,9 @@
"test:all": "npm run lint && npm run test:cov"
},
"dependencies": {
+ "@expo/vector-icons": "^13.0.0",
"@react-native-async-storage/async-storage": "1.21.0",
+ "@react-navigation/bottom-tabs": "^6.5.20",
"@react-navigation/native": "^6.1.10",
"@react-navigation/native-stack": "^6.9.18",
"expo": "^50.0.14",
diff --git a/templates/boilerplate/src/__tests__/App.test.tsx b/templates/boilerplate/src/__tests__/App.test.tsx
index 7fc6b2d..0e388cb 100644
--- a/templates/boilerplate/src/__tests__/App.test.tsx
+++ b/templates/boilerplate/src/__tests__/App.test.tsx
@@ -3,6 +3,7 @@ import RootNavigator from 'src/navigators/RootNavigator';
import render from 'src/test/render';
test('renders', async () => {
+ jest.useFakeTimers();
render();
expect(await screen.findByText(/Open up App.tsx/)).toBeDefined();
});
diff --git a/templates/boilerplate/src/navigators/DashboardStack.tsx b/templates/boilerplate/src/navigators/DashboardStack.tsx
new file mode 100644
index 0000000..610788b
--- /dev/null
+++ b/templates/boilerplate/src/navigators/DashboardStack.tsx
@@ -0,0 +1,16 @@
+import { createNativeStackNavigator } from '@react-navigation/native-stack';
+import React from 'react';
+import HomeScreen from 'src/screens/HomeScreen/HomeScreen';
+import InformationScreen from '../screens/InformationScreen/InformationScreen';
+import { DashboardTabParamList } from './navigatorTypes';
+
+const Dashboard = createNativeStackNavigator();
+
+export default function DashboardStack() {
+ return (
+
+
+
+
+ );
+}
diff --git a/templates/boilerplate/src/navigators/RootNavigator.tsx b/templates/boilerplate/src/navigators/RootNavigator.tsx
index 0602444..39b738b 100644
--- a/templates/boilerplate/src/navigators/RootNavigator.tsx
+++ b/templates/boilerplate/src/navigators/RootNavigator.tsx
@@ -1,12 +1,30 @@
-import { createNativeStackNavigator } from '@react-navigation/native-stack';
-import HomeScreen from 'src/screens/HomeScreen/HomeScreen';
+import {
+ NativeStackNavigationOptions,
+ createNativeStackNavigator,
+} from '@react-navigation/native-stack';
+import TabNavigator from './TabNavigator';
+
+const navigatorScreenOptions: NativeStackNavigationOptions = {
+ headerShadowVisible: false,
+};
const Stack = createNativeStackNavigator();
export default function RootNavigator() {
return (
-
-
+
+
+
+ {/*
+ screens that are navigable outside of tabs go here. This can include:
+ - authentication screens (only render tab navigator conditionally)
+ - screens that should not display bottom tab bar and that might be
+ navigated to from a screen from multiple tabs
+ */}
);
}
diff --git a/templates/boilerplate/src/navigators/TabNavigator.tsx b/templates/boilerplate/src/navigators/TabNavigator.tsx
new file mode 100644
index 0000000..be54a60
--- /dev/null
+++ b/templates/boilerplate/src/navigators/TabNavigator.tsx
@@ -0,0 +1,50 @@
+import { MaterialCommunityIcons } from '@expo/vector-icons';
+import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
+import SettingsScreen from '../screens/SettingsScreen/SettingsScreen';
+import DashboardStack from './DashboardStack';
+import { TabsParamList } from './navigatorTypes';
+
+const Tab = createBottomTabNavigator();
+
+function HomeIcon({ focused = false, color = 'gray' }) {
+ return ;
+}
+
+function AccountIcon({ focused = false, color = 'gray' }) {
+ return (
+
+ );
+}
+
+export default function TabNavigator() {
+ return (
+
+
+
+
+ );
+}
diff --git a/templates/boilerplate/src/navigators/navigatorTypes.tsx b/templates/boilerplate/src/navigators/navigatorTypes.tsx
index 5695f70..cd97dbf 100644
--- a/templates/boilerplate/src/navigators/navigatorTypes.tsx
+++ b/templates/boilerplate/src/navigators/navigatorTypes.tsx
@@ -1,6 +1,40 @@
-// add types for navigation here
-// key: screen name
-// value: params (use undefined if accepts none)
+import { NavigatorScreenParams } from '@react-navigation/native';
+import { NativeStackScreenProps } from '@react-navigation/native-stack';
+
export type RootStackParamList = {
+ Tabs: NavigatorScreenParams;
+};
+
+export type TabsParamList = {
+ DashboardTab: NavigatorScreenParams;
+ SettingsTab: NavigatorScreenParams;
+};
+
+export type DashboardTabParamList = {
Home: undefined;
+ Information: { owner: string } | undefined;
+};
+
+export type SettingsTabParamList = {
+ Settings: undefined;
};
+
+/* ----------------------------------------------------------------
+ Derived types -- these should not need to be frequently modified
+ -------------------------------------------------------------*/
+export type TabName = keyof TabsParamList;
+export type RootRouteName = keyof RootStackParamList;
+export type AppRouteName =
+ | keyof RootStackParamList
+ | keyof DashboardTabParamList
+ | keyof SettingsTabParamList;
+
+export type HomeScreenProp = NativeStackScreenProps<
+ DashboardTabParamList,
+ 'Home'
+>;
+
+export type InformationScreenProp = NativeStackScreenProps<
+ DashboardTabParamList,
+ 'Information'
+>;
diff --git a/templates/boilerplate/src/screens/HomeScreen/HomeScreen.tsx b/templates/boilerplate/src/screens/HomeScreen/HomeScreen.tsx
index 8fde09e..ba298d5 100644
--- a/templates/boilerplate/src/screens/HomeScreen/HomeScreen.tsx
+++ b/templates/boilerplate/src/screens/HomeScreen/HomeScreen.tsx
@@ -1,10 +1,18 @@
+import { useNavigation } from '@react-navigation/native';
import { StatusBar } from 'expo-status-bar';
-import { StyleSheet, Text, View } from 'react-native';
+import { Button, StyleSheet, Text, View } from 'react-native';
+import { HomeScreenProp } from 'src/navigators/navigatorTypes';
export default function HomeScreen() {
+ const navigation = useNavigation();
+
return (
Open up App.tsx to start working on your app!
+
);
diff --git a/templates/boilerplate/src/screens/InformationScreen/InformationScreen.tsx b/templates/boilerplate/src/screens/InformationScreen/InformationScreen.tsx
new file mode 100644
index 0000000..dbab34d
--- /dev/null
+++ b/templates/boilerplate/src/screens/InformationScreen/InformationScreen.tsx
@@ -0,0 +1,25 @@
+import { useRoute } from '@react-navigation/native';
+import { StatusBar } from 'expo-status-bar';
+import { StyleSheet, Text, View } from 'react-native';
+import { InformationScreenProp } from 'src/navigators/navigatorTypes';
+
+export default function InformationScreen() {
+ const { params } = useRoute();
+
+ return (
+
+ Information Screen
+ {params && {params.owner}’s Profile}
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: '#fff',
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+});
diff --git a/templates/reactNavigation/src/screens/HomeScreen/HomeScreen.tsx b/templates/boilerplate/src/screens/SettingsScreen/SettingsScreen.tsx
similarity index 77%
rename from templates/reactNavigation/src/screens/HomeScreen/HomeScreen.tsx
rename to templates/boilerplate/src/screens/SettingsScreen/SettingsScreen.tsx
index 8fde09e..85bfdd2 100644
--- a/templates/reactNavigation/src/screens/HomeScreen/HomeScreen.tsx
+++ b/templates/boilerplate/src/screens/SettingsScreen/SettingsScreen.tsx
@@ -1,10 +1,10 @@
import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, View } from 'react-native';
-export default function HomeScreen() {
+export default function SettingsScreen() {
return (
- Open up App.tsx to start working on your app!
+ Settings Screen
);
diff --git a/templates/reactNavigation/src/navigators/RootNavigator.tsx b/templates/reactNavigation/src/navigators/RootNavigator.tsx
deleted file mode 100644
index 0602444..0000000
--- a/templates/reactNavigation/src/navigators/RootNavigator.tsx
+++ /dev/null
@@ -1,12 +0,0 @@
-import { createNativeStackNavigator } from '@react-navigation/native-stack';
-import HomeScreen from 'src/screens/HomeScreen/HomeScreen';
-
-const Stack = createNativeStackNavigator();
-
-export default function RootNavigator() {
- return (
-
-
-
- );
-}
diff --git a/templates/reactNavigation/src/navigators/navigatorTypes.tsx b/templates/reactNavigation/src/navigators/navigatorTypes.tsx
deleted file mode 100644
index 5695f70..0000000
--- a/templates/reactNavigation/src/navigators/navigatorTypes.tsx
+++ /dev/null
@@ -1,6 +0,0 @@
-// add types for navigation here
-// key: screen name
-// value: params (use undefined if accepts none)
-export type RootStackParamList = {
- Home: undefined;
-};
diff --git a/templates/reactNavigation/src/types/global.d.ts b/templates/reactNavigation/src/types/global.d.ts
deleted file mode 100644
index 688efff..0000000
--- a/templates/reactNavigation/src/types/global.d.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-// eslint-disable-next-line @typescript-eslint/no-unused-vars
-import { RootStackParamList } from '../navigators/navigatorTypes';
-
-declare global {
- namespace ReactNavigation {
- // eslint-disable-next-line @typescript-eslint/no-empty-interface
- interface RootParamList extends RootStackParamList {}
- }
-}